From de31c9feea91a9e073e3158e350e2ca26e56cbc7 Mon Sep 17 00:00:00 2001 From: Yunus Emre Kalkan Date: Mon, 26 Jan 2026 11:33:15 +0300 Subject: [PATCH] Add support for JS frameworks in InstallLibsService Enhanced InstallLibsService to detect and handle JavaScript frameworks (React Native, React, Vue, Next.js) by parsing package.json and running yarn accordingly. Updated project discovery to include these frameworks while avoiding overlap with Angular and .NET projects. --- .../Volo/Abp/Cli/LIbs/InstallLibsService.cs | 175 ++++++++++++++++-- 1 file changed, 155 insertions(+), 20 deletions(-) diff --git a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs index 0141195cb5..eda89d277a 100644 --- a/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs +++ b/framework/src/Volo.Abp.Cli.Core/Volo/Abp/Cli/LIbs/InstallLibsService.cs @@ -6,11 +6,21 @@ using System.Threading.Tasks; using Microsoft.Extensions.FileSystemGlobbing; using Microsoft.Extensions.FileSystemGlobbing.Abstractions; using Microsoft.Extensions.Logging; +using Newtonsoft.Json.Linq; using Volo.Abp.Cli.Utils; using Volo.Abp.DependencyInjection; namespace Volo.Abp.Cli.LIbs; +public enum JavaScriptFrameworkType +{ + None, + ReactNative, + React, + Vue, + NextJs +} + public class InstallLibsService : IInstallLibsService, ITransientDependency { private readonly static List ExcludeDirectory = new List() @@ -78,36 +88,161 @@ public class InstallLibsService : IInstallLibsService, ITransientDependency await CleanAndCopyResources(projectDirectory); } + + // JavaScript frameworks (React Native, React, Vue, Next.js) + if (projectPath.EndsWith("package.json")) + { + var frameworkType = DetectFrameworkTypeFromPackageJson(projectPath); + + if (frameworkType == JavaScriptFrameworkType.ReactNative) + { + Logger.LogInformation($"Installing dependencies for React Native project: {projectDirectory}"); + NpmHelper.RunYarn(projectDirectory); + } + else if (frameworkType == JavaScriptFrameworkType.React) + { + Logger.LogInformation($"Installing dependencies for React project: {projectDirectory}"); + NpmHelper.RunYarn(projectDirectory); + } + else if (frameworkType == JavaScriptFrameworkType.Vue) + { + Logger.LogInformation($"Installing dependencies for Vue.js project: {projectDirectory}"); + NpmHelper.RunYarn(projectDirectory); + } + else if (frameworkType == JavaScriptFrameworkType.NextJs) + { + Logger.LogInformation($"Installing dependencies for Next.js project: {projectDirectory}"); + NpmHelper.RunYarn(projectDirectory); + } + } + } + } + + private JavaScriptFrameworkType DetectFrameworkTypeFromPackageJson(string packageJsonFilePath) + { + if (!File.Exists(packageJsonFilePath)) + { + return JavaScriptFrameworkType.None; + } + + try + { + var packageJsonContent = File.ReadAllText(packageJsonFilePath); + var packageJson = JObject.Parse(packageJsonContent); + + var dependencies = new HashSet(StringComparer.OrdinalIgnoreCase); + + // Check dependencies + if (packageJson["dependencies"] is JObject deps) + { + foreach (var prop in deps.Properties()) + { + dependencies.Add(prop.Name); + } + } + + // Check devDependencies + if (packageJson["devDependencies"] is JObject devDeps) + { + foreach (var prop in devDeps.Properties()) + { + dependencies.Add(prop.Name); + } + } + + // Check for React Native first (has priority over React) + if (dependencies.Contains("react-native")) + { + return JavaScriptFrameworkType.ReactNative; + } + + // Check for other frameworks + if (dependencies.Contains("next")) + { + return JavaScriptFrameworkType.NextJs; + } + + if (dependencies.Contains("vue")) + { + return JavaScriptFrameworkType.Vue; + } + + if (dependencies.Contains("react")) + { + return JavaScriptFrameworkType.React; + } + + return JavaScriptFrameworkType.None; + } + catch (Exception ex) + { + Logger.LogWarning($"Failed to parse package.json at {packageJsonFilePath}: {ex.Message}"); + return JavaScriptFrameworkType.None; } } private List FindAllProjects(string directory) { - return Directory.GetFiles(directory, "*.csproj", SearchOption.AllDirectories) - .Union(Directory.GetFiles(directory, "angular.json", SearchOption.AllDirectories)) + var projects = new List(); + + // Find .csproj files (existing logic) + var csprojFiles = Directory.GetFiles(directory, "*.csproj", SearchOption.AllDirectories) .Where(file => ExcludeDirectory.All(x => file.IndexOf(x + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) == -1)) .Where(file => { - if (file.EndsWith(".csproj")) + var packageJsonFilePath = Path.Combine(Path.GetDirectoryName(file), "package.json"); + if (!File.Exists(packageJsonFilePath)) + { + return false; + } + + using (var reader = File.OpenText(file)) + { + var fileTexts = reader.ReadToEnd(); + return fileTexts.Contains("Microsoft.NET.Sdk.Web") || + fileTexts.Contains("Microsoft.NET.Sdk.Razor") || + fileTexts.Contains("Microsoft.NET.Sdk.BlazorWebAssembly"); + } + }); + + projects.AddRange(csprojFiles); + + // Find angular.json files (existing logic) + var angularFiles = Directory.GetFiles(directory, "angular.json", SearchOption.AllDirectories) + .Where(file => ExcludeDirectory.All(x => file.IndexOf(x + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) == -1)); + + projects.AddRange(angularFiles); + + // Find package.json files for JavaScript frameworks + var packageJsonFiles = Directory.GetFiles(directory, "package.json", SearchOption.AllDirectories) + .Where(file => ExcludeDirectory.All(x => file.IndexOf(x + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) == -1)) + .Where(packageJsonFile => + { + var packageJsonDirectory = Path.GetDirectoryName(packageJsonFile); + if (packageJsonDirectory == null) { - var packageJsonFilePath = Path.Combine(Path.GetDirectoryName(file), "package.json"); - if (!File.Exists(packageJsonFilePath)) - { - return false; - } - - using (var reader = File.OpenText(file)) - { - var fileTexts = reader.ReadToEnd(); - return fileTexts.Contains("Microsoft.NET.Sdk.Web") || - fileTexts.Contains("Microsoft.NET.Sdk.Razor") || - fileTexts.Contains("Microsoft.NET.Sdk.BlazorWebAssembly"); - } + return false; } - return true; - }) - .OrderBy(x => x) - .ToList(); + + // Skip if already handled by Angular or .NET detection + if (File.Exists(Path.Combine(packageJsonDirectory, "angular.json"))) + { + return false; + } + + if (Directory.GetFiles(packageJsonDirectory, "*.csproj", SearchOption.TopDirectoryOnly).Any()) + { + return false; + } + + // Check if it's a JavaScript framework project + var frameworkType = DetectFrameworkTypeFromPackageJson(packageJsonFile); + return frameworkType != JavaScriptFrameworkType.None; + }); + + projects.AddRange(packageJsonFiles); + + return projects.OrderBy(x => x).ToList(); } private async Task CleanAndCopyResources(string fileDirectory)