diff --git a/src/ElectronNET.CLI/Commands/BuildCommand.cs b/src/ElectronNET.CLI/Commands/BuildCommand.cs index 2d4322b0..66cefc77 100644 --- a/src/ElectronNET.CLI/Commands/BuildCommand.cs +++ b/src/ElectronNET.CLI/Commands/BuildCommand.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using System.Text.Json; using ElectronNET.CLI.Commands.Actions; namespace ElectronNET.CLI.Commands @@ -139,28 +140,138 @@ public Task ExecuteAsync() File.Copy(parser.Arguments[_paramPackageJson][0], Path.Combine(tempPath, "package.json"), true); } - var checkForNodeModulesDirPath = Path.Combine(tempPath, "node_modules"); + // Read electron version from manifest file and update package.json BEFORE npm install + string manifestFileName = "electron.manifest.json"; - if (Directory.Exists(checkForNodeModulesDirPath) == false || parser.Contains(_paramForceNodeInstall) || parser.Contains(_paramPackageJson)) + if (parser.Arguments.ContainsKey(_manifest)) + { + manifestFileName = parser.Arguments[_manifest].First(); + } - Console.WriteLine("Start npm install..."); - ProcessHelper.CmdExecute("npm install --production", tempPath); + // Read electron version from manifest file + string electronVersion = "23.2.0"; // default fallback version + string manifestPath = Path.Combine(Directory.GetCurrentDirectory(), manifestFileName); + + Console.WriteLine($"Reading electronVersion from manifest file: {manifestPath}"); + + if (File.Exists(manifestPath)) + { + try + { + string manifestContent = File.ReadAllText(manifestPath); + using (JsonDocument document = JsonDocument.Parse(manifestContent)) + { + if (document.RootElement.TryGetProperty("electronVersion", out JsonElement electronVersionElement)) + { + string manifestElectronVersion = electronVersionElement.GetString(); + if (!string.IsNullOrWhiteSpace(manifestElectronVersion)) + { + electronVersion = manifestElectronVersion; + Console.WriteLine($"Using Electron version {electronVersion} from manifest file"); + } + else + { + Console.WriteLine($"electronVersion property found but empty in manifest file, using fallback version {electronVersion}"); + } + } + else + { + Console.WriteLine($"electronVersion property not found in manifest file, using fallback version {electronVersion}"); + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Warning: Could not read electronVersion from manifest file: {ex.Message}"); + Console.WriteLine($"Using fallback Electron version {electronVersion}"); + } + } + else + { + Console.WriteLine($"Warning: Manifest file not found at {manifestPath}"); + Console.WriteLine($"Using fallback Electron version {electronVersion}"); + } - Console.WriteLine("ElectronHostHook handling started..."); + // Update package.json with electronVersion directly in C# before npm install + string packageJsonPath = Path.Combine(tempPath, "package.json"); + if (File.Exists(packageJsonPath)) + { + try + { + string packageJsonContent = File.ReadAllText(packageJsonPath); + using (JsonDocument packageDocument = JsonDocument.Parse(packageJsonContent)) + { + var packageJsonObject = new Dictionary(); + + // Copy existing properties + foreach (var property in packageDocument.RootElement.EnumerateObject()) + { + if (property.Name == "devDependencies") + { + var devDeps = new Dictionary(); + foreach (var dep in property.Value.EnumerateObject()) + { + devDeps[dep.Name] = dep.Value.GetString(); + } + // Update electron version + devDeps["electron"] = $"^{electronVersion}"; + packageJsonObject["devDependencies"] = devDeps; + } + else if (property.Value.ValueKind == JsonValueKind.String) + { + packageJsonObject[property.Name] = property.Value.GetString(); + } + else if (property.Value.ValueKind == JsonValueKind.Object) + { + var subObject = new Dictionary(); + foreach (var subProp in property.Value.EnumerateObject()) + { + subObject[subProp.Name] = subProp.Value.GetString(); + } + packageJsonObject[property.Name] = subObject; + } + else + { + packageJsonObject[property.Name] = property.Value.ToString(); + } + } + + // Ensure devDependencies exists and contains electron + if (!packageJsonObject.ContainsKey("devDependencies")) + { + packageJsonObject["devDependencies"] = new Dictionary(); + } + var devDependencies = (Dictionary)packageJsonObject["devDependencies"]; + devDependencies["electron"] = $"^{electronVersion}"; + + string updatedPackageJson = JsonSerializer.Serialize(packageJsonObject, new JsonSerializerOptions + { + WriteIndented = true + }); + + File.WriteAllText(packageJsonPath, updatedPackageJson); + Console.WriteLine($"Updated package.json with Electron version {electronVersion}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Warning: Could not update package.json with electronVersion: {ex.Message}"); + } + } - string electronhosthookDir = Path.Combine(Directory.GetCurrentDirectory(), "ElectronHostHook"); + var checkForNodeModulesDirPath = Path.Combine(tempPath, "node_modules"); - if (Directory.Exists(electronhosthookDir)) - { - string hosthookDir = Path.Combine(tempPath, "ElectronHostHook"); - DirectoryCopy.Do(electronhosthookDir, hosthookDir, true, new List() { "node_modules" }); + if (Directory.Exists(checkForNodeModulesDirPath) == false || parser.Contains(_paramForceNodeInstall) || parser.Contains(_paramPackageJson)) + Console.WriteLine("Start npm install..."); - Console.WriteLine("Start npm install for hosthooks..."); - ProcessHelper.CmdExecute("npm install", hosthookDir); + ProcessHelper.CmdExecute("npm install --production", tempPath); - // ToDo: Not sure if this runs under linux/macos - ProcessHelper.CmdExecute(@"npx tsc -p . --sourceMap false", hosthookDir); - } + // Update build helper and configuration files after npm install + Console.WriteLine("Create electron-builder configuration file..."); + ProcessHelper.CmdExecute( + string.IsNullOrWhiteSpace(version) + ? $"node build-helper.js {manifestFileName}" + : $"node build-helper.js {manifestFileName} {version}", tempPath); Console.WriteLine("Build Electron Desktop Application..."); @@ -189,23 +300,8 @@ public Task ExecuteAsync() electronParams = parser.Arguments[_paramElectronParams][0]; } - // ToDo: Make the same thing easer with native c# - we can save a tmp file in production code :) - Console.WriteLine("Create electron-builder configuration file..."); - - string manifestFileName = "electron.manifest.json"; - - if (parser.Arguments.ContainsKey(_manifest)) - { - manifestFileName = parser.Arguments[_manifest].First(); - } - - ProcessHelper.CmdExecute( - string.IsNullOrWhiteSpace(version) - ? $"node build-helper.js {manifestFileName}" - : $"node build-helper.js {manifestFileName} {version}", tempPath); - Console.WriteLine($"Package Electron App for Platform {platformInfo.ElectronPackerPlatform}..."); - ProcessHelper.CmdExecute($"npx electron-builder --config=./bin/electron-builder.json --{platformInfo.ElectronPackerPlatform} --{electronArch} -c.electronVersion=30.0.3 {electronParams}", tempPath); + ProcessHelper.CmdExecute($"npx electron-builder --config=./bin/electron-builder.json --{platformInfo.ElectronPackerPlatform} --{electronArch} -c.electronVersion={electronVersion} {electronParams}", tempPath); Console.WriteLine("... done"); diff --git a/src/ElectronNET.CLI/Commands/StartElectronCommand.cs b/src/ElectronNET.CLI/Commands/StartElectronCommand.cs index 03382ecd..af58fe0d 100644 --- a/src/ElectronNET.CLI/Commands/StartElectronCommand.cs +++ b/src/ElectronNET.CLI/Commands/StartElectronCommand.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Runtime.InteropServices; using System.Threading.Tasks; +using System.Text.Json; using ElectronNET.CLI.Commands.Actions; namespace ElectronNET.CLI.Commands @@ -118,6 +119,108 @@ public Task ExecuteAsync() DeployEmbeddedElectronFiles.Do(tempPath); + // Update package.json with electronVersion from manifest before npm install + string manifestFileName = "electron.manifest.json"; + if (parser.Arguments.ContainsKey(_manifest)) + { + manifestFileName = parser.Arguments[_manifest].First(); + } + + // Read electron version from manifest file + string electronVersion = "23.2.0"; // default fallback version + string manifestPath = Path.Combine(aspCoreProjectPath, manifestFileName); + + if (File.Exists(manifestPath)) + { + try + { + string manifestContent = File.ReadAllText(manifestPath); + using (JsonDocument document = JsonDocument.Parse(manifestContent)) + { + if (document.RootElement.TryGetProperty("electronVersion", out JsonElement electronVersionElement)) + { + string manifestElectronVersion = electronVersionElement.GetString(); + if (!string.IsNullOrWhiteSpace(manifestElectronVersion)) + { + electronVersion = manifestElectronVersion; + Console.WriteLine($"Using Electron version {electronVersion} from manifest file"); + } + } + } + } + catch (Exception ex) + { + Console.WriteLine($"Warning: Could not read electronVersion from manifest file: {ex.Message}"); + } + } + + // Update package.json with electronVersion directly in C# before npm install + string packageJsonPath = Path.Combine(tempPath, "package.json"); + if (File.Exists(packageJsonPath)) + { + try + { + string packageJsonContent = File.ReadAllText(packageJsonPath); + using (JsonDocument packageDocument = JsonDocument.Parse(packageJsonContent)) + { + var packageJsonObject = new Dictionary(); + + // Copy existing properties + foreach (var property in packageDocument.RootElement.EnumerateObject()) + { + if (property.Name == "devDependencies") + { + var devDeps = new Dictionary(); + foreach (var dep in property.Value.EnumerateObject()) + { + devDeps[dep.Name] = dep.Value.GetString(); + } + // Update electron version + devDeps["electron"] = $"^{electronVersion}"; + packageJsonObject["devDependencies"] = devDeps; + } + else if (property.Value.ValueKind == JsonValueKind.String) + { + packageJsonObject[property.Name] = property.Value.GetString(); + } + else if (property.Value.ValueKind == JsonValueKind.Object) + { + var subObject = new Dictionary(); + foreach (var subProp in property.Value.EnumerateObject()) + { + subObject[subProp.Name] = subProp.Value.GetString(); + } + packageJsonObject[property.Name] = subObject; + } + else + { + packageJsonObject[property.Name] = property.Value.ToString(); + } + } + + // Ensure devDependencies exists and contains electron + if (!packageJsonObject.ContainsKey("devDependencies")) + { + packageJsonObject["devDependencies"] = new Dictionary(); + } + var devDependencies = (Dictionary)packageJsonObject["devDependencies"]; + devDependencies["electron"] = $"^{electronVersion}"; + + string updatedPackageJson = JsonSerializer.Serialize(packageJsonObject, new JsonSerializerOptions + { + WriteIndented = true + }); + + File.WriteAllText(packageJsonPath, updatedPackageJson); + Console.WriteLine($"Updated package.json with Electron version {electronVersion}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Warning: Could not update package.json with electronVersion: {ex.Message}"); + } + } + var nodeModulesDirPath = Path.Combine(tempPath, "node_modules"); Console.WriteLine("node_modules missing in: " + nodeModulesDirPath); @@ -125,6 +228,9 @@ public Task ExecuteAsync() Console.WriteLine("Start npm install..."); ProcessHelper.CmdExecute("npm install", tempPath); + // Execute build-helper.js to setup other configurations after npm install + ProcessHelper.CmdExecute($"node build-helper.js {manifestFileName}", tempPath); + Console.WriteLine("ElectronHostHook handling started..."); string electronhosthookDir = Path.Combine(Directory.GetCurrentDirectory(), "ElectronHostHook"); diff --git a/src/ElectronNET.Host/build-helper.js b/src/ElectronNET.Host/build-helper.js index d8ebc944..98ad41f6 100644 --- a/src/ElectronNET.Host/build-helper.js +++ b/src/ElectronNET.Host/build-helper.js @@ -8,20 +8,30 @@ const builderConfiguration = { ...manifestFile.build }; if(process.argv.length > 3) { builderConfiguration.buildVersion = process.argv[3]; } + +// @ts-ignore +const packageJson = require('./package'); + +// Update package.json if buildVersion is provided if(builderConfiguration.hasOwnProperty('buildVersion')) { - // @ts-ignore - const packageJson = require('./package'); packageJson.name = dasherize(manifestFile.name || 'electron-net'); packageJson.author = manifestFile.author || ''; packageJson.version = builderConfiguration.buildVersion; packageJson.description = manifestFile.description || ''; - fs.writeFile('./package.json', JSON.stringify(packageJson), (error) => { + // Write updated package.json + fs.writeFile('./package.json', JSON.stringify(packageJson, null, 2), (error) => { if(error) { console.log(error.message); } }); - +} + +// Note: electronVersion is now handled directly in C# before npm install +// No need to update it here anymore + +// Update package-lock.json if it exists +if(builderConfiguration.hasOwnProperty('buildVersion')) { try { // @ts-ignore const packageLockJson = require('./package-lock'); diff --git a/src/ElectronNET.WebApp/electron.manifest.json b/src/ElectronNET.WebApp/electron.manifest.json index f423bab1..faf1526c 100644 --- a/src/ElectronNET.WebApp/electron.manifest.json +++ b/src/ElectronNET.WebApp/electron.manifest.json @@ -5,6 +5,7 @@ }, "environment": "Production", "singleInstance": false, + "electronVersion": "25.9.0", "build": { "appId": "com.electronnetapidemos.app", "productName": "ElectronNET API Demos",