diff --git a/Directory.Packages.props b/Directory.Packages.props index 5b6839ec30..0a7d88c504 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -168,7 +168,7 @@ - + diff --git a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json index 18730b51d6..981500451a 100644 --- a/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json +++ b/abp_io/AbpIoLocalization/AbpIoLocalization/Www/Localization/Resources/en.json @@ -1553,6 +1553,15 @@ "IntegrateToYourKubernetesCluster_Description1": "Connect your local development environment to a local or remote Kubernetes cluster, where that cluster already runs your microservice solution.", "IntegrateToYourKubernetesCluster_Description2": "Access any service in Kubernetes with their service name as DNS, just like they are running in your local computer.", "IntegrateToYourKubernetesCluster_Description3": "Intercept any service in that cluster, so all the traffic to the intercepted service is automatically redirected to your service that is running in your local machine. When your service needs to use any service in Kubernetes, the traffic is redirected back to the cluster, just like your local service is running inside the Kubernetes.", + "AskOurAiAssistant": "Ask Our AI Assistant", + "AskOurAiAssistant_Description1": "Build faster with an AI that actually understands your ABP project. The ABP AI Assistant answers your technical questions, explains your code, and helps you solve problems directly inside ABP Studio — with full awareness of your project’s structure. You can even send screenshots or code files to get precise, context-based guidance.", + "AskOurAiAssistant_Description2": "What It Helps You Do", + "AskOurAiAssistant_Description3": "Ask anything about your ABP project — domain layer, modules, configuration, entities, services, or UI.", + "AskOurAiAssistant_Description4": "Get smart, code-aware explanations tailored to your solution.", + "AskOurAiAssistant_Description5": "Generate snippets and scaffolding suggestions instantly.", + "AskOurAiAssistant_Description6": "Fix errors faster with context-aware debugging support.", + "AskOurAiAssistant_Description7": "Learn ABP best practices as you build.", + "AskOurAiAssistant_Description8": "Whether you're generating new features, debugging an issue, or exploring a module, the AI Assistant gives you actionable, project-specific answers — right when you need them.", "GetInformed": "Get Informed", "Studio_GetInformed_Description1": "Leave your contact information to get informed and try it first when ABP Studio has been launched.", "Studio_GetInformed_Description2": "Planned preview release date: Q3 of 2023.", diff --git a/docs/en/Community-Articles/2025-11-15-Announcing-SSR-Support/article.md b/docs/en/Community-Articles/2025-11-15-Announcing-SSR-Support/article.md index 51688dc5a7..ba7f0696be 100644 --- a/docs/en/Community-Articles/2025-11-15-Announcing-SSR-Support/article.md +++ b/docs/en/Community-Articles/2025-11-15-Announcing-SSR-Support/article.md @@ -33,7 +33,7 @@ You can easily add SSR support to your existing ABP Angular application using th # Generate SSR configuration for your project ng generate @abp/ng.schematics:ssr-add -# Or using the short form +# Alternatively, you can use the short form ng g @abp/ng.schematics:ssr-add ``` diff --git a/docs/en/cli/index.md b/docs/en/cli/index.md index 7decaa658c..3a3d0c2304 100644 --- a/docs/en/cli/index.md +++ b/docs/en/cli/index.md @@ -7,11 +7,7 @@ # ABP CLI -ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions or ABP Studio features. - -> With **v8.2+**, the old/legacy ABP CLI has been replaced with a new CLI system to align with the new templating system and [ABP Studio](../studio/index.md). The new ABP CLI commands are explained in this documentation. However, if you want to learn more about the differences between the old and new CLIs, want to learn the reason for the change, or need guidance to use the old ABP CLI, please refer to the [Old vs New CLI](differences-between-old-and-new-cli.md) documentation. -> -> You may need to remove the Old CLI before installing the New CLI, by running the following command: `dotnet tool uninstall -g Volo.Abp.Cli` +ABP CLI (Command Line Interface) is a command line tool to perform some common operations for ABP based solutions or [ABP Studio](../studio/index.md) features. ## Installation @@ -29,16 +25,16 @@ dotnet tool update -g Volo.Abp.Studio.Cli ## Global Options -While each command may have a set of options, there are some global options that can be used with any command; +While each command may have a set of options, there are some global options that can be used with any command: -* `--skip-cli-version-check` or `-scvc`: Skips to check the latest version of the ABP CLI. If you don't specify, it will check the latest version and shows a warning message if there is a newer version of the ABP CLI. -- `--skip-extension-version-check` or `-sevc`: Skips to check the latest version of the ABP CLI extensions. If you don't specify, it will check the latest version and download the latest version if there is a newer version of the ABP CLI extensions. +* `--skip-cli-version-check` or `-scvc`: Skips checking the latest version of the ABP CLI. If you don't specify, it will check the latest version and shows a warning message if there is a newer version of the ABP CLI. +- `--skip-extension-version-check` or `-sevc`: Skips checking the latest version of the ABP CLI extensions. If you don't specify, it will check the latest version and download the latest version if there is a newer version of the ABP CLI extensions. * `--old`: ABP CLI has two variations: `Volo.Abp.Studio.Cli` and `Volo.Abp.Cli`. New features/templates are added to the `Volo.Abp.Studio.Cli`. But if you want to use the old version, you can use this option **at the end of your commands**. For example, `abp new Acme.BookStore --old`. * `--help` or `-h`: Shows help for the specified command. ## Commands -Here, is the list of all available commands before explaining their details: +Here is the list of all available commands before explaining their details: * **[`help`](../cli#help)**: Shows help on the usage of the ABP CLI. * **[`cli`](../cli#cli)**: Update or remove ABP CLI. diff --git a/docs/en/release-info/release-notes.md b/docs/en/release-info/release-notes.md index f0c58f0013..bf335fa7a2 100644 --- a/docs/en/release-info/release-notes.md +++ b/docs/en/release-info/release-notes.md @@ -14,9 +14,9 @@ Also see the following notes about ABP releases: * [ABP Studio release notes](../studio/release-notes.md) * [Change logs for ABP pro packages](https://abp.io/pro-releases) -## 10.0 (2025-10-01) +## 10.0 (2025-11-18) -This is currently a RC (release-candidate) and you can see the detailed **[blog post / announcement](https://abp.io/community/announcements/announcing-abp-10-0-release-candidate-86lrnyox)** for the v10.0 release. +See the detailed **[blog post / announcement](https://abp.io/community/announcements/abp.io-platform-10.0-final-has-been-released-spknn925)** for the v10.0 release. * Upgraded to .NET 10.0 * Upgraded to `Blazorise` **v1.8.6** diff --git a/docs/en/tutorials/microservice/part-01.md b/docs/en/tutorials/microservice/part-01.md index a3529019a5..7006226e21 100644 --- a/docs/en/tutorials/microservice/part-01.md +++ b/docs/en/tutorials/microservice/part-01.md @@ -25,7 +25,7 @@ } ```` -Follow the *[Get Started](../../get-started/microservice.md)* guide to create a new layered web application with the following configurations: +Follow the *[Get Started](../../get-started/microservice.md)* guide to create a new microservice solution with the following configurations: * **Solution name**: `CloudCrm` {{if DB == "EF"}} @@ -82,4 +82,4 @@ You can see the *[Microservice Solution Template](../../solution-templates/micro ## Summary -In this part, you've created the initial microservice solution, which already contains a few infrastructure services. We will create our first business service in the [next part](part-02.md). \ No newline at end of file +In this part, you've created the initial microservice solution, which already contains a few infrastructure services. We will create our first business service in the [next part](part-02.md). diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs index 95e07a06e0..214b866197 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc.NewtonsoftJson/Volo/Abp/AspNetCore/Mvc/NewtonsoftJson/AbpAspNetCoreMvcNewtonsoftModule.cs @@ -13,7 +13,7 @@ public class AbpAspNetCoreMvcNewtonsoftModule : AbpModule { context.Services.AddMvcCore().AddNewtonsoftJson(); - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { options.SerializerSettings.ContractResolver = diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index c3fc470ed8..ad8d8c1c28 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -165,7 +165,7 @@ public class AbpAspNetCoreMvcModule : AbpModule context.Services.AddSingleton(); context.Services.TryAddEnumerable(ServiceDescriptor.Transient()); - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((mvcOptions, serviceProvider) => { mvcOptions.AddAbp(context.Services); diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs index f2bac81316..89af08fd43 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs @@ -13,7 +13,7 @@ public static class MvcCoreBuilderExtensions { public static IMvcCoreBuilder AddAbpJson(this IMvcCoreBuilder builder) { - builder.Services.AddOptions() + builder.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip; diff --git a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs index 27f69f3ba4..b840119d18 100644 --- a/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs +++ b/framework/src/Volo.Abp.BlazoriseUI/Components/ObjectExtending/ExtensionProperties.razor.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Immutable; +using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Components; using Microsoft.Extensions.Localization; @@ -29,8 +30,13 @@ public partial class ExtensionProperties : Component public ImmutableList Properties { get; set; } = ImmutableList.Empty; - protected async override Task OnInitializedAsync() + protected override async Task OnInitializedAsync() { - Properties = await ObjectExtensionManager.Instance.GetPropertiesAndCheckPolicyAsync(ServiceProvider); + Properties = + (await ObjectExtensionManager.Instance.GetPropertiesAndCheckPolicyAsync(ServiceProvider)) + .Where(p => ModalType == ExtensionPropertyModalType.CreateModal + ? p.UI.CreateModal.IsVisible + : p.UI.EditModal.IsVisible) + .ToImmutableList(); } } diff --git a/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionOptionsExtensions.cs b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionOptionsExtensions.cs new file mode 100644 index 0000000000..43230c4dbb --- /dev/null +++ b/framework/src/Volo.Abp.Core/Microsoft/Extensions/DependencyInjection/ServiceCollectionOptionsExtensions.cs @@ -0,0 +1,22 @@ +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using Volo.Abp.Options; + +namespace Microsoft.Extensions.DependencyInjection; + +public static class ServiceCollectionOptionsExtensions +{ + /// + /// You should only use this method to register options if you need to continue using the ServiceProvider to get other options in your Options configuration method. + /// Otherwise, please use the default AddOptions method for better performance. + /// + /// + /// + /// + public static OptionsBuilder AddAbpOptions(this IServiceCollection services) + where TOptions : class + { + services.TryAddSingleton, AbpUnnamedOptionsManager>(); + return services.AddOptions(); + } +} diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs index 04ea98644e..4ec967ed01 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/AbpApplicationBase.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.InteropServices; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Configuration; @@ -200,7 +201,13 @@ public abstract class AbpApplicationBase : IAbpApplication using var scope = ServiceProvider.CreateScope(); var abpHostEnvironment = scope.ServiceProvider.GetRequiredService(); var configuration = scope.ServiceProvider.GetRequiredService(); - return abpHostEnvironment.IsDevelopment() && configuration.GetValue("Abp:Telemetry:IsEnabled") != false; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX) || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + return abpHostEnvironment.IsDevelopment() && configuration.GetValue("Abp:Telemetry:IsEnabled") != false; + } + + return false; } //TODO: We can extract a new class for this diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs index e01768c418..c57d51e6f2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Providers/TelemetrySolutionInfoEnricher.cs @@ -114,7 +114,10 @@ internal sealed class TelemetrySolutionInfoEnricher : TelemetryActivityEventEnri } var moduleJsonFileContent = File.ReadAllText(modulePath); - using var moduleDoc = JsonDocument.Parse(moduleJsonFileContent); + using var moduleDoc = JsonDocument.Parse(moduleJsonFileContent, new JsonDocumentOptions + { + AllowTrailingCommas = true + }); if (!moduleDoc.RootElement.TryGetProperty("imports", out var imports)) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Storage/TelemetryActivityStorage.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Storage/TelemetryActivityStorage.cs index 6796af7179..b37ec15d71 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Storage/TelemetryActivityStorage.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Activity/Storage/TelemetryActivityStorage.cs @@ -25,6 +25,8 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep public TelemetryActivityStorage() { CreateDirectoryIfNotExist(); + + DeleteExistingOldInformation(); State = LoadState(); } @@ -166,6 +168,22 @@ public class TelemetryActivityStorage : ITelemetryActivityStorage, ISingletonDep } } + private static void DeleteExistingOldInformation() + { + try + { + var file = new FileInfo(TelemetryPaths.ActivityStorage); + if (file.Exists && file.CreationTime < new DateTime(2025, 12, 01)) + { + file.Delete(); + } + } + catch + { + // Ignored + } + } + private static TelemetryActivityStorageState LoadState() { try diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/ActivityPropertyNames.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/ActivityPropertyNames.cs index 924cd1dd7d..0157c61bb8 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/ActivityPropertyNames.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/ActivityPropertyNames.cs @@ -12,6 +12,7 @@ public static class ActivityPropertyNames public const string IpAddress = "IpAddress"; public const string IsFirstSession = "IsFirstSession"; public const string DeviceId = "DeviceId"; + public const string UserDeviceId = "UserDeviceId"; public const string DeviceLanguage = "DeviceLanguage"; public const string OperatingSystem = "OperatingSystem"; public const string CountryIsoCode = "CountryIsoCode"; diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/DeviceManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/DeviceManager.cs index e3993886a0..393f974e98 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/DeviceManager.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Constants/DeviceManager.cs @@ -133,7 +133,7 @@ static internal class DeviceManager { try { - return GetProcessorIdForWindows(); + return GetBaseBoardSerialNumberForWindows(); } catch { @@ -142,10 +142,10 @@ static internal class DeviceManager return GetWindowsMachineUniqueId(); } - private static string GetProcessorIdForWindows() + private static string GetBaseBoardSerialNumberForWindows() { using (var managementObjectSearcher = - new System.Management.ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor")) + new System.Management.ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard")) { using (var searcherObj = managementObjectSearcher.Get()) { @@ -156,7 +156,7 @@ static internal class DeviceManager var managementObjectEnumerator = searcherObj.GetEnumerator(); managementObjectEnumerator.MoveNext(); - return managementObjectEnumerator.Current.GetPropertyValue("ProcessorId").ToString()!; + return managementObjectEnumerator.Current.GetPropertyValue("SerialNumber").ToString()!; } } } diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/AbpStudioDetector.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/AbpStudioDetector.cs index 3d35c7192a..b37760cb04 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/AbpStudioDetector.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/AbpStudioDetector.cs @@ -40,7 +40,10 @@ internal sealed class AbpStudioDetector : SoftwareDetector return null; } using var fs = new FileStream(ideStateJsonPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using var doc = JsonDocument.Parse(fs); + using var doc = JsonDocument.Parse(fs, new JsonDocumentOptions + { + AllowTrailingCommas = true + }); return doc.RootElement.TryGetProperty("theme", out var themeElement) ? themeElement.GetString() : null; } @@ -55,7 +58,10 @@ internal sealed class AbpStudioDetector : SoftwareDetector } using var fs = new FileStream(extensionsFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - using var doc = JsonDocument.Parse(fs); + using var doc = JsonDocument.Parse(fs, new JsonDocumentOptions + { + AllowTrailingCommas = true + }); if (doc.RootElement.TryGetProperty("Extensions", out var extensionsElement) && extensionsElement.ValueKind == JsonValueKind.Array) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/VisualStudioCodeDetector.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/VisualStudioCodeDetector.cs index 72fda0f500..52559663c2 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/VisualStudioCodeDetector.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/EnvironmentInspection/Detectors/VisualStudioCodeDetector.cs @@ -77,7 +77,10 @@ internal sealed class VisualStudioCodeDetector : SoftwareDetector { try { - using var jsonDoc = JsonDocument.Parse(File.ReadAllText(productJson)); + using var jsonDoc = JsonDocument.Parse(File.ReadAllText(productJson), new JsonDocumentOptions + { + AllowTrailingCommas = true + }); var root = jsonDoc.RootElement; if (root.TryGetProperty("version", out var versionProp)) { @@ -105,7 +108,10 @@ internal sealed class VisualStudioCodeDetector : SoftwareDetector { try { - using var json = JsonDocument.Parse( File.ReadAllText(settingsPath)); + using var json = JsonDocument.Parse( File.ReadAllText(settingsPath), new JsonDocumentOptions + { + AllowTrailingCommas = true + }); var root = json.RootElement; if (root.TryGetProperty("theme", out var themeProp)) { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Helpers/AbpPackageMetadataReader.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Helpers/AbpPackageMetadataReader.cs index f9ce98a2e5..446462c527 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Helpers/AbpPackageMetadataReader.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/Helpers/AbpPackageMetadataReader.cs @@ -49,11 +49,13 @@ static internal class AbpProjectMetadataReader private static AbpProjectMetaData ReadOrCreateMetadata(string packagePath) { - var fileContent = File.ReadAllText(packagePath); var metadata = new AbpProjectMetaData(); - using var document = JsonDocument.Parse(fileContent); + using var document = JsonDocument.Parse(fileContent, new JsonDocumentOptions + { + AllowTrailingCommas = true + }); var root = document.RootElement; if (TryGetProjectId(root,out var projectId)) diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/TelemetryService.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/TelemetryService.cs index 8a2e3b4382..2f684acd29 100644 --- a/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/TelemetryService.cs +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Internal/Telemetry/TelemetryService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Volo.Abp.DependencyInjection; using Volo.Abp.Internal.Telemetry.Activity.Contracts; using Volo.Abp.Internal.Telemetry.Constants; @@ -11,17 +12,11 @@ namespace Volo.Abp.Internal.Telemetry; public class TelemetryService : ITelemetryService, IScopedDependency { - private readonly ITelemetryActivitySender _telemetryActivitySender; - private readonly ITelemetryActivityEventBuilder _telemetryActivityEventBuilder; - private readonly ITelemetryActivityStorage _telemetryActivityStorage; + private readonly IServiceScopeFactory _serviceScopeFactory; - public TelemetryService(ITelemetryActivitySender telemetryActivitySender, - ITelemetryActivityEventBuilder telemetryActivityEventBuilder, - ITelemetryActivityStorage telemetryActivityStorage) + public TelemetryService(IServiceScopeFactory serviceScopeFactory) { - _telemetryActivitySender = telemetryActivitySender; - _telemetryActivityEventBuilder = telemetryActivityEventBuilder; - _telemetryActivityStorage = telemetryActivityStorage; + _serviceScopeFactory = serviceScopeFactory; } @@ -74,24 +69,37 @@ public class TelemetryService : ITelemetryService, IScopedDependency { _ = Task.Run(async () => { - await BuildAndSendActivityAsync(context); + using var scope = _serviceScopeFactory.CreateScope(); + + var telemetryActivityEventBuilder = scope.ServiceProvider.GetRequiredService(); + var telemetryActivityStorage = scope.ServiceProvider.GetRequiredService(); + var telemetryActivitySender = scope.ServiceProvider.GetRequiredService(); + + await BuildAndSendActivityAsync(context, + telemetryActivityEventBuilder, + telemetryActivityStorage, + telemetryActivitySender); }); return Task.CompletedTask; } - private async Task BuildAndSendActivityAsync(ActivityContext context) + private static async Task BuildAndSendActivityAsync( + ActivityContext context, + ITelemetryActivityEventBuilder telemetryActivityEventBuilder, + ITelemetryActivityStorage telemetryActivityStorage, + ITelemetryActivitySender telemetryActivitySender) { try { - var activityEvent = await _telemetryActivityEventBuilder.BuildAsync(context); + var activityEvent = await telemetryActivityEventBuilder.BuildAsync(context); if (activityEvent is null) { return; } - _telemetryActivityStorage.SaveActivity(activityEvent); - await _telemetryActivitySender.TrySendQueuedActivitiesAsync(); + telemetryActivityStorage.SaveActivity(activityEvent); + await telemetryActivitySender.TrySendQueuedActivitiesAsync(); } catch { diff --git a/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpUnnamedOptionsManager.cs b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpUnnamedOptionsManager.cs new file mode 100644 index 0000000000..894df70e75 --- /dev/null +++ b/framework/src/Volo.Abp.Core/Volo/Abp/Options/AbpUnnamedOptionsManager.cs @@ -0,0 +1,34 @@ +using Microsoft.Extensions.Options; + +namespace Volo.Abp.Options; + +/// +/// This Options manager is similar to Microsoft UnnamedOptionsManager but without the locking mechanism. +/// Prevent deadlocks when accessing options in multiple threads. +/// +/// +public class AbpUnnamedOptionsManager : IOptions + where TOptions : class +{ + private readonly IOptionsFactory _factory; + private TOptions? _value; + + public AbpUnnamedOptionsManager(IOptionsFactory factory) + { + _factory = factory; + } + + public TOptions Value + { + get + { + if (_value is { } value) + { + return value; + } + + _value = _factory.Create(Microsoft.Extensions.Options.Options.DefaultName); + return _value; + } + } +} diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs index ea35831d86..4b35ee5f25 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs +++ b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonNewtonsoftModule.cs @@ -10,7 +10,7 @@ public class AbpJsonNewtonsoftModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( diff --git a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs index 0a5066cec1..2679cca96c 100644 --- a/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs +++ b/framework/src/Volo.Abp.Json.SystemTextJson/Volo/Abp/Json/SystemTextJson/AbpJsonSystemTextJsonModule.cs @@ -15,7 +15,7 @@ public class AbpJsonSystemTextJsonModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { // If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters. diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiFormConfiguration.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiFormConfiguration.cs index d1d041a9b1..9a95cd6481 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiFormConfiguration.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ExtensionPropertyUiFormConfiguration.cs @@ -6,4 +6,9 @@ public class ExtensionPropertyUiFormConfiguration /// Default: true. /// public bool IsVisible { get; set; } = true; + + /// + /// Default: false. + /// + public bool IsReadOnly { get; set; } = false; } diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs index 9a13b17028..40b9e8feb6 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/Modularity/ModuleExtensionConfigurationHelper.cs @@ -175,6 +175,10 @@ public static class ModuleExtensionConfigurationHelper property.DefaultValueFactory = propertyConfig.DefaultValueFactory; property.Lookup = propertyConfig.UI.Lookup; property.UI.Order = propertyConfig.UI.Order; + property.UI.CreateModal.IsVisible = propertyConfig.UI.OnCreateForm.IsVisible; + property.UI.CreateModal.IsReadOnly = propertyConfig.UI.OnCreateForm.IsReadOnly; + property.UI.EditModal.IsVisible = propertyConfig.UI.OnEditForm.IsVisible; + property.UI.EditModal.IsReadOnly = propertyConfig.UI.OnEditForm.IsReadOnly; property.Policy = propertyConfig.Policy; foreach (var configuration in propertyConfig.Configuration) { diff --git a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs index e5ed79b99e..35c40e8043 100644 --- a/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs +++ b/framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ObjectExtensionPropertyInfo.cs @@ -90,16 +90,34 @@ public class ObjectExtensionPropertyInfo : IHasNameWithLocalizableDisplayName, I { public int Order { get; set; } + public ExtensionPropertyUICreateModal CreateModal { get; set; } + public ExtensionPropertyUIEditModal EditModal { get; set; } public ExtensionPropertyUI() { + CreateModal = new ExtensionPropertyUICreateModal(); EditModal = new ExtensionPropertyUIEditModal(); } } + public class ExtensionPropertyUICreateModal + { + /// + /// Default: true. + /// + public bool IsVisible { get; set; } = true; + + public bool IsReadOnly { get; set; } + } + public class ExtensionPropertyUIEditModal { + /// + /// Default: true. + /// + public bool IsVisible { get; set; } = true; + public bool IsReadOnly { get; set; } } } diff --git a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs index 1238d766be..d63ca833eb 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; using JetBrains.Annotations; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerUI; using Volo.Abp.Content; @@ -21,7 +21,7 @@ public static class AbpSwaggerGenServiceCollectionExtensions { Func remoteStreamContentSchemaFactory = () => new OpenApiSchema() { - Type = "string", + Type = JsonSchemaType.String, Format = "binary" }; @@ -42,7 +42,7 @@ public static class AbpSwaggerGenServiceCollectionExtensions { var authorizationUrl = new Uri($"{authority.TrimEnd('/')}{authorizationEndpoint.EnsureStartsWith('/')}"); var tokenUrl = new Uri($"{authority.TrimEnd('/')}{tokenEndpoint.EnsureStartsWith('/')}"); - + return services .AddAbpSwaggerGen() .AddSwaggerGen( @@ -62,19 +62,9 @@ public static class AbpSwaggerGenServiceCollectionExtensions } }); - options.AddSecurityRequirement(new OpenApiSecurityRequirement + options.AddSecurityRequirement(document => new OpenApiSecurityRequirement() { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "oauth2" - } - }, - Array.Empty() - } + [new OpenApiSecuritySchemeReference("oauth2", document)] = [] }); setupAction?.Invoke(options); @@ -100,7 +90,7 @@ public static class AbpSwaggerGenServiceCollectionExtensions swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes; swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryUrl; }); - + return services .AddAbpSwaggerGen() .AddSwaggerGen( @@ -112,24 +102,15 @@ public static class AbpSwaggerGenServiceCollectionExtensions OpenIdConnectUrl = new Uri(RemoveTenantPlaceholders(discoveryUrl)) }); - options.AddSecurityRequirement(new OpenApiSecurityRequirement + options.AddSecurityRequirement(document => new OpenApiSecurityRequirement() { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "oidc" - } - }, - Array.Empty() - } + [new OpenApiSecuritySchemeReference("oauth2", document)] = [] }); + setupAction?.Invoke(options); }); } - + private static string RemoveTenantPlaceholders(string url) { return url diff --git a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleDocumentFilter.cs b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleDocumentFilter.cs index b6dc661410..8c4f06d786 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleDocumentFilter.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleDocumentFilter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Microsoft.AspNetCore.Mvc.Abstractions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; namespace Volo.Abp.Swashbuckle; @@ -13,7 +13,7 @@ public class AbpSwashbuckleDocumentFilter : IDocumentFilter protected virtual string[] ActionUrlPrefixes { get; set; } = new[] { "Volo." }; protected virtual string RegexConstraintPattern => @":regex\(([^()]*)\)"; - + public virtual void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { var actionUrls = context.ApiDescriptions @@ -28,6 +28,20 @@ public class AbpSwashbuckleDocumentFilter : IDocumentFilter swaggerDoc .Paths .RemoveAll(path => !actionUrls.Contains(path.Key)); + + var tags = new List(); + foreach (var path in swaggerDoc.Paths) + { + if (path.Value.Operations != null) + { + tags.AddRange(path.Value.Operations.SelectMany(x => + { + return x.Value.Tags?.Select(t => t.Name ?? string.Empty) ?? Array.Empty(); + })); + } + } + tags = tags.Distinct().ToList(); + swaggerDoc.Tags?.RemoveAll(tag => tag.Name == null || !tags.Contains(tag.Name)); } protected virtual string? RemoveRouteParameterConstraints(ActionDescriptor actionDescriptor) @@ -49,7 +63,7 @@ public class AbpSwashbuckleDocumentFilter : IDocumentFilter { break; } - + route = route.Remove(startIndex, (endIndex - startIndex)); } diff --git a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleEnumSchemaFilter.cs b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleEnumSchemaFilter.cs index b6a20d2ad2..afd6a141dc 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleEnumSchemaFilter.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Volo/Abp/Swashbuckle/AbpSwashbuckleEnumSchemaFilter.cs @@ -1,22 +1,22 @@ -using Microsoft.OpenApi.Any; -using Microsoft.OpenApi.Models; +using System; +using System.Text.Json.Nodes; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; -using System; namespace Volo.Abp.Swashbuckle; public class AbpSwashbuckleEnumSchemaFilter : ISchemaFilter { - public void Apply(OpenApiSchema schema, SchemaFilterContext context) + public void Apply(IOpenApiSchema schema, SchemaFilterContext context) { - if (context.Type.IsEnum) + if (schema is OpenApiSchema openApiScheme && context.Type.IsEnum) { - schema.Enum.Clear(); - schema.Type = "string"; - schema.Format = null; + openApiScheme.Enum?.Clear(); + openApiScheme.Type = JsonSchemaType.String; + openApiScheme.Format = null; foreach (var name in Enum.GetNames(context.Type)) { - schema.Enum.Add(new OpenApiString($"{name}")); + openApiScheme.Enum?.Add(JsonNode.Parse($"\"{name}\"")!); } } } diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs index 121ec62a85..5382d3db46 100644 --- a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs @@ -19,7 +19,7 @@ public class AbpJsonSystemTextJsonTestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { if (options.JsonSerializerOptions.TypeInfoResolver != null) @@ -43,7 +43,7 @@ public class AbpJsonNewtonsoftTestModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { options.JsonSerializerSettings.ContractResolver = new AbpCamelCasePropertyNamesContractResolver( diff --git a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs index 4435f1dcf0..a2234aa14a 100644 --- a/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs +++ b/framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/AbpMemoryDbTestModule.cs @@ -34,7 +34,7 @@ public class AbpMemoryDbTestModule : AbpModule options.AddRepository(); }); - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((options, rootServiceProvider) => { options.JsonSerializerOptions.Converters.Add(new EntityJsonConverter()); diff --git a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs index 47447e1fdf..c239da4234 100644 --- a/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs +++ b/modules/blogging/app/Volo.BloggingTestApp/BloggingTestAppModule.cs @@ -11,7 +11,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account; diff --git a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs index 1f451f58d9..bfc910c7c6 100644 --- a/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.HttpApi.Host/CmsKitHttpApiHostModule.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Hosting; using Volo.CmsKit.EntityFrameworkCore; using Volo.CmsKit.MultiTenancy; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.AspNetCore.MultiTenancy; diff --git a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs index 623b417bc7..933dc8f50b 100644 --- a/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.IdentityServer/CmsKitIdentityServerModule.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Volo.CmsKit.MultiTenancy; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account; diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Host/CmsKitWebHostModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Host/CmsKitWebHostModule.cs index 522771c77b..7054a6f1fe 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Host/CmsKitWebHostModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Host/CmsKitWebHostModule.cs @@ -2,7 +2,7 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using System.IO; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.DataProtection; diff --git a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs index c216a6ba38..e8169fbfef 100644 --- a/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs +++ b/modules/cms-kit/host/Volo.CmsKit.Web.Unified/CmsKitWebUnifiedModule.cs @@ -3,7 +3,7 @@ using System.IO; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Volo.Abp; using Volo.Abp.Account; using Volo.Abp.Account.Web; diff --git a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs index 3d49767cdb..4a7f511bff 100644 --- a/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs +++ b/modules/docs/app/VoloDocs.Web/VoloDocsWebModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account.Web; diff --git a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml index 899a8e6473..89ee5db51e 100644 --- a/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml +++ b/modules/docs/src/Volo.Docs.Admin.Web/Pages/Docs/Admin/Documents/Index.cshtml @@ -29,7 +29,7 @@
- +
@@ -86,7 +86,7 @@
- + @@ -149,7 +149,7 @@ - +
@L["Format"].Value
@@ -161,9 +161,6 @@
- - -
@L["LastSignificantUpdateTime"].Value
@@ -185,7 +182,9 @@ - + + + diff --git a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs index d261068adb..67b5d0bfa7 100644 --- a/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs +++ b/modules/identity/src/Volo.Abp.Identity.AspNetCore/Volo/Abp/Identity/AspNetCore/AbpIdentityAspNetCoreModule.cs @@ -47,7 +47,7 @@ public class AbpIdentityAspNetCoreModule : AbpModule public override void PostConfigureServices(ServiceConfigurationContext context) { - context.Services.AddOptions() + context.Services.AddAbpOptions() .Configure((securityStampValidatorOptions, serviceProvider) => { var abpRefreshingPrincipalOptions = serviceProvider.GetRequiredService>().Value; diff --git a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs index 0938f87e6c..c565273532 100644 --- a/modules/openiddict/app/OpenIddict.Demo.API/Program.cs +++ b/modules/openiddict/app/OpenIddict.Demo.API/Program.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Authentication.JwtBearer; using OpenIddict.Demo.API; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.SwaggerGen; using Swashbuckle.AspNetCore.SwaggerUI; @@ -42,19 +42,9 @@ builder.Services.AddSwaggerGen(options => } }); - options.AddSecurityRequirement(new OpenApiSecurityRequirement + options.AddSecurityRequirement(document => new OpenApiSecurityRequirement() { - { - new OpenApiSecurityScheme - { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "oauth2" - } - }, - Array.Empty() - } + [new OpenApiSecuritySchemeReference("oauth2", document)] = [] }); }); diff --git a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs index cbb97606bd..4671a82ad6 100644 --- a/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs +++ b/modules/setting-management/app/Volo.Abp.SettingManagement.DemoApp/DemoAppModule.cs @@ -3,7 +3,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Volo.Abp.Account; using Volo.Abp.Account.Web; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; diff --git a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts index 8d1e478864..3b77913d2e 100644 --- a/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts +++ b/npm/ng-packs/packages/core/src/lib/guards/permission.guard.ts @@ -4,10 +4,11 @@ import { CanActivateFn, Router, RouterStateSnapshot, + UrlTree, } from '@angular/router'; import { HttpErrorResponse } from '@angular/common/http'; import { Observable, of } from 'rxjs'; -import { filter, take, tap } from 'rxjs/operators'; +import { map, take } from 'rxjs/operators'; import { AuthService, IAbpGuard } from '../abstracts'; import { findRoute, getRoutePath } from '../utils/route-utils'; import { RoutesService, PermissionService, HttpErrorReporterService } from '../services'; @@ -25,7 +26,7 @@ export class PermissionGuard implements IAbpGuard { protected readonly permissionService = inject(PermissionService); protected readonly httpErrorReporter = inject(HttpErrorReporterService); - canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { let { requiredPolicy } = route.data || {}; if (!requiredPolicy) { @@ -38,12 +39,19 @@ export class PermissionGuard implements IAbpGuard { } return this.permissionService.getGrantedPolicy$(requiredPolicy).pipe( - filter(Boolean), take(1), - tap(access => { - if (!access && this.authService.isAuthenticated) { + map(access => { + if (access) return true; + + if (route.data?.['redirectUrl']) { + return this.router.parseUrl(route.data['redirectUrl']); + } + + if (this.authService.isAuthenticated) { this.httpErrorReporter.reportError({ status: 403 } as HttpErrorResponse); } + + return false; }), ); } @@ -77,12 +85,19 @@ export const permissionGuard: CanActivateFn = ( } return permissionService.getGrantedPolicy$(requiredPolicy).pipe( - filter(Boolean), take(1), - tap(access => { - if (!access && authService.isAuthenticated) { + map(access => { + if (access) return true; + + if (route.data?.['redirectUrl']) { + return router.parseUrl(route.data['redirectUrl']); + } + + if (authService.isAuthenticated) { httpErrorReporter.reportError({ status: 403 } as HttpErrorResponse); } + + return false; }), ); }; diff --git a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts index 1a0ae3e147..45f3b46d80 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/permission.guard.spec.ts @@ -39,6 +39,15 @@ describe('authGuard', () => { component: DummyComponent, canActivate: [permissionGuard], }, + { + path: 'redirect-test', + component: DummyComponent, + canActivate: [permissionGuard], + data: { + requiredPolicy: 'TestPolicy', + redirectUrl: '/zibzib', + }, + }, ]; beforeEach(() => { @@ -103,4 +112,12 @@ describe('authGuard', () => { await RouterTestingHarness.create('/zibzib'); expect(TestBed.inject(Router).url).toEqual('/zibzib'); }); + + it('should redirect to redirectUrl when the grantedPolicy is false and redirectUrl is provided', async () => { + permissionService.getGrantedPolicy$.andReturn(of(false)); + await RouterTestingHarness.create('/redirect-test'); + + expect(TestBed.inject(Router).url).toEqual('/zibzib'); + expect(httpErrorReporter.reportError).not.toHaveBeenCalled(); + }); }); diff --git a/npm/ng-packs/packages/schematics/src/collection.json b/npm/ng-packs/packages/schematics/src/collection.json index b84de19733..1116a7e15a 100644 --- a/npm/ng-packs/packages/schematics/src/collection.json +++ b/npm/ng-packs/packages/schematics/src/collection.json @@ -35,6 +35,11 @@ "factory": "./commands/change-theme", "schema": "./commands/change-theme/schema.json" }, + "ai-config": { + "description": "Generates AI configuration files for Angular projects", + "factory": "./commands/ai-config", + "schema": "./commands/ai-config/schema.json" + }, "server": { "factory": "./commands/ssr-add/server", "description": "Create an Angular server app.", diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/claude/.claude/CLAUDE.md @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/copilot/.github/copilot-instructions.md @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/cursor/.cursor/rules/cursor.mdc @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/gemini/.gemini/GEMINI.md @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/junie/.junie/guidelines.md b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/junie/.junie/guidelines.md new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/junie/.junie/guidelines.md @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md new file mode 100644 index 0000000000..32dfab0275 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/files/windsurf/.windsurf/rules/guidelines.md @@ -0,0 +1,186 @@ +# 💻 ABP Full-Stack Development Rules +_Expert Guidelines for .NET Backend (ABP) and Angular Frontend Development_ + +You are a **senior full-stack developer** specializing in **ABP Framework (.NET)** and **Angular (TypeScript)**. +You write **clean, maintainable, and modular** code following **ABP, ASP.NET Core, and Angular best practices**. + +--- + +## 🧩 1. General Principles +- Maintain a clear separation between backend (ABP/.NET) and frontend (Angular) layers. +- Follow **modular architecture** — each layer or feature should be independently testable and reusable. +- Always adhere to **official ABP documentation** ([docs.abp.io](https://docs.abp.io)) and **Angular official guides**. +- Prioritize **readability, maintainability, and performance**. +- Write **idiomatic** and **self-documenting** code. + +--- + +## ⚙️ 2. ABP / .NET Development Rules + +### Code Style and Structure +- Follow ABP’s standard folder structure: + - `*.Application`, `*.Domain`, `*.EntityFrameworkCore`, `*.HttpApi` +- Write concise, idiomatic C# code using modern language features. +- Apply **modular and layered design** (Domain, Application, Infrastructure, UI). +- Prefer **LINQ** and **lambda expressions** for collection operations. +- Use **descriptive method and variable names** (`GetActiveUsers`, `CalculateTotalAmount`). + +### Naming Conventions +- **PascalCase** → Classes, Methods, Properties +- **camelCase** → Local variables and private fields +- **UPPER_CASE** → Constants +- Prefix interfaces with **`I`** (e.g., `IUserRepository`). + +### C# and .NET Usage +- Use **C# 10+ features** (records, pattern matching, null-coalescing assignment). +- Utilize **ABP modules** (Permission Management, Setting Management, Audit Logging). +- Integrate **Entity Framework Core** with ABP’s repository abstractions. + +### Syntax and Formatting +- Follow [Microsoft C# Coding Conventions](https://learn.microsoft.com/dotnet/csharp/fundamentals/coding-style/coding-conventions). +- Use `var` when the type is clear. +- Use `string interpolation` and null-conditional operators. +- Keep code consistent and well-formatted. + +### Error Handling and Validation +- Use exceptions only for exceptional cases. +- Log errors via ABP’s built-in logging or a compatible provider. +- Validate models with **DataAnnotations** or **FluentValidation**. +- Rely on ABP’s global exception middleware for unified responses. +- Return consistent HTTP status codes and error DTOs. + +### API Design +- Build RESTful APIs via `HttpApi` layer and **ABP conventional controllers**. +- Use **attribute-based routing** and versioning when needed. +- Apply **action filters/middleware** for cross-cutting concerns (auditing, authorization). + +### Performance Optimization +- Use `async/await` for I/O operations. +- Use `IDistributedCache` over `IMemoryCache`. +- Avoid N+1 queries — include relations explicitly. +- Implement pagination with `PagedResultDto`. + +### Key Conventions +- Use **Dependency Injection** via ABP’s DI system. +- Apply **repository pattern** or EF Core directly as needed. +- Use **AutoMapper** or ABP object mapping for DTOs. +- Implement **background jobs** with ABP’s job system or `IHostedService`. +- Follow **domain-driven design (DDD)** principles: + - Business rules in Domain layer. + - Use `AuditedAggregateRoot`, `FullAuditedEntity`, etc. +- Avoid unnecessary dependencies between layers. + +### Testing +- Use **xUnit**, **Shouldly**, and **NSubstitute** for testing. +- Write **unit and integration tests** per module (`Application.Tests`, `Domain.Tests`). +- Mock dependencies properly and use ABP’s test base classes. + +### Security +- Use **OpenIddict** for authentication & authorization. +- Implement permission checks through ABP’s infrastructure. +- Enforce **HTTPS** and properly configure **CORS**. + +### API Documentation +- Use **Swagger / OpenAPI** (Swashbuckle or NSwag). +- Add XML comments to controllers and DTOs. +- Follow ABP’s documentation conventions for module APIs. + +**Reference Best Practices:** +- [Domain Services](https://abp.io/docs/latest/framework/architecture/best-practices/domain-services) +- [Repositories](https://abp.io/docs/latest/framework/architecture/best-practices/repositories) +- [Entities](https://abp.io/docs/latest/framework/architecture/best-practices/entities) +- [Application Services](https://abp.io/docs/latest/framework/architecture/best-practices/application-services) +- [DTOs](https://abp.io/docs/latest/framework/architecture/best-practices/data-transfer-objects) +- [Entity Framework Integration](https://abp.io/docs/latest/framework/architecture/best-practices/entity-framework-core-integration) + +--- + +## 🌐 3. Angular / TypeScript Development Rules + +### TypeScript Best Practices +- Enable **strict type checking** in `tsconfig.json`. +- Use **type inference** when the type is obvious. +- Avoid `any`; use `unknown` or generics instead. +- Use interfaces and types for clarity and structure. + +### Angular Best Practices +- Prefer **standalone components** (no `NgModules`). +- Do **NOT** set `standalone: true` manually — it’s default. +- Use **signals** for state management. +- Implement **lazy loading** for feature routes. +- Avoid `@HostBinding` / `@HostListener`; use `host` object in decorators. +- Use **`NgOptimizedImage`** for static images (not base64). + +### Components +- Keep components small, focused, and reusable. +- Use `input()` and `output()` functions instead of decorators. +- Use `computed()` for derived state. +- Always set `changeDetection: ChangeDetectionStrategy.OnPush`. +- Use **inline templates** for small components. +- Prefer **Reactive Forms** over template-driven forms. +- Avoid `ngClass` → use `[class]` bindings. +- Avoid `ngStyle` → use `[style]` bindings. + +### State Management +- Manage **local component state** with signals. +- Use **`computed()`** for derived data. +- Keep state transformations **pure and predictable**. +- Avoid `mutate()` on signals — use `update()` or `set()`. + +### Templates +- Use **native control flow** (`@if`, `@for`, `@switch`) instead of structural directives. +- Keep templates minimal and declarative. +- Use the **async pipe** for observable bindings. + +### Services +- Design services for **single responsibility**. +- Provide services using `providedIn: 'root'`. +- Use the **`inject()` function** instead of constructor injection. + +### Component Replacement +ABP Angular provides a powerful **component replacement** system via `ReplaceableComponentsService`: + +**Key Features:** +- Replace ABP default components (Roles, Users, Tenants, etc.) with custom implementations +- Replace layouts (Application, Account, Empty) +- Replace UI elements (Logo, Routes, NavItems) + +**Basic Usage:** +```typescript +import { ReplaceableComponentsService } from '@abp/ng.core'; +import { eIdentityComponents } from '@abp/ng.identity'; + +constructor(private replaceableComponents: ReplaceableComponentsService) { + this.replaceableComponents.add({ + component: YourCustomComponent, + key: eIdentityComponents.Roles, + }); +} +``` + +**Important Notes:** +- Component templates must include `` for layouts +- Use the second parameter as `true` for runtime replacement (refreshes route) +- Runtime replacement clears component state and re-runs initialization logic + +**📚 Full Documentation:** +For detailed examples, layout replacement, and advanced scenarios: +[Component Replacement Guide](https://abp.io/docs/latest/framework/ui/angular/customization-user-interface) + +--- + +## 🔒 4. Combined Full-Stack Practices +- Ensure backend and frontend follow consistent **DTO contracts** and **naming conventions**. +- Maintain shared models (e.g., via a `contracts` package or OpenAPI generation). +- Version APIs carefully and handle changes in Angular clients. +- Use ABP’s **CORS**, **Swagger**, and **Identity** modules to simplify frontend integration. +- Apply **global error handling** and consistent response wrappers in both layers. +- Monitor performance with tools like **Application Insights**, **ABP auditing**, or **Angular profiler**. + +--- + +## ✅ Summary +This document defines a unified standard for developing **ABP + Angular full-stack applications**, ensuring: +- Code is **modular**, **performant**, and **maintainable**. +- Teams follow **consistent conventions** across backend and frontend. +- Every layer (Domain, Application, UI) is **clean, testable, and scalable**. diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/index.ts b/npm/ng-packs/packages/schematics/src/commands/ai-config/index.ts new file mode 100644 index 0000000000..2cc2da1165 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/index.ts @@ -0,0 +1,118 @@ +import { + Rule, + SchematicsException, + Tree, + apply, + url, + mergeWith, + MergeStrategy, + filter, + chain, +} from '@angular-devkit/schematics'; +import { join, normalize } from '@angular-devkit/core'; +import { AiConfigSchema, AiTool } from './model'; +import { getWorkspace } from '../../utils'; + +export default function (options: AiConfigSchema): Rule { + return async (tree: Tree) => { + if (!options.tool || options.tool.trim() === '') { + console.log('ℹ️ No AI tools selected. Skipping configuration generation.'); + console.log(''); + console.log('💡 Usage examples:'); + console.log(' ng g @abp/ng.schematics:ai-config --tool=claude,cursor'); + console.log(' ng g @abp/ng.schematics:ai-config --tool="claude, cursor"'); + console.log(' ng g @abp/ng.schematics:ai-config --tool=gemini --tool=cursor'); + console.log(' ng g @abp/ng.schematics:ai-config --tool=gemini --target-project=my-app'); + console.log(''); + console.log('Available tools: claude, copilot, cursor, gemini, junie, windsurf'); + return tree; + } + + const tools = options.tool.split(/[\s,]+/).filter(t => t) as AiTool[]; + + const validTools: AiTool[] = ['claude', 'copilot', 'cursor', 'gemini', 'junie', 'windsurf']; + const invalidTools = tools.filter(tool => !validTools.includes(tool)); + if (invalidTools.length > 0) { + throw new SchematicsException( + `Invalid AI tool(s): ${invalidTools.join(', ')}. Valid options are: ${validTools.join(', ')}`, + ); + } + + if (tools.length === 0) { + console.log('ℹ️ No AI tools selected. Skipping configuration generation.'); + return tree; + } + + const workspace = await getWorkspace(tree); + let targetPath = '/'; + + if (options.targetProject) { + const trimmedTargetProject = options.targetProject.trim(); + const project = workspace.projects.get(trimmedTargetProject); + if (!project) { + throw new SchematicsException(`Project "${trimmedTargetProject}" not found in workspace.`); + } + targetPath = normalize(project.root); + } + + console.log('🚀 Generating AI configuration files...'); + console.log(`📁 Target path: ${targetPath}`); + console.log(`🤖 Selected tools: ${tools.join(', ')}`); + + const rules: Rule[] = tools.map(tool => + generateConfigForTool(tool, targetPath, options.overwrite || false), + ); + + return chain([ + ...rules, + (tree: Tree) => { + console.log('✅ AI configuration files generated successfully!'); + console.log('\n📝 Generated files:'); + + tools.forEach(tool => { + const configPath = getConfigPath(tool, targetPath); + console.log(` - ${configPath}`); + }); + + console.log('\n💡 Tip: Restart your IDE or AI tool to apply the new configurations.'); + + return tree; + }, + ]); + }; +} + +function generateConfigForTool(tool: AiTool, targetPath: string, overwrite: boolean): Rule { + return (tree: Tree) => { + const configPath = getConfigPath(tool, targetPath); + + if (tree.exists(configPath) && !overwrite) { + console.log(`⚠️ Configuration file already exists: ${configPath}`); + console.log(` Use --overwrite flag to replace existing files.`); + return tree; + } + + const sourceDir = `./files/${tool}`; + const source = apply(url(sourceDir), [ + filter(path => { + return !path.endsWith('.DS_Store'); + }), + ]); + + return mergeWith(source, overwrite ? MergeStrategy.Overwrite : MergeStrategy.Default); + }; +} + +function getConfigPath(tool: AiTool, basePath: string): string { + const configFiles: Record = { + claude: '.claude/CLAUDE.md', + copilot: '.github/copilot-instructions.md', + cursor: '.cursor/rules/cursor.mdc', + gemini: '.gemini/GEMINI.md', + junie: '.junie/guidelines.md', + windsurf: '.windsurf/rules/guidelines.md', + }; + + const configFile = configFiles[tool]; + return join(normalize(basePath), configFile); +} diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/model.ts b/npm/ng-packs/packages/schematics/src/commands/ai-config/model.ts new file mode 100644 index 0000000000..ab871971c2 --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/model.ts @@ -0,0 +1,12 @@ +export type AiTool = 'claude' | 'copilot' | 'cursor' | 'gemini' | 'junie' | 'windsurf'; + +export interface AiConfigSchema { + tool?: string; + targetProject?: string; + overwrite?: boolean; +} + +export interface AiConfigFile { + path: string; + content: string; +} diff --git a/npm/ng-packs/packages/schematics/src/commands/ai-config/schema.json b/npm/ng-packs/packages/schematics/src/commands/ai-config/schema.json new file mode 100644 index 0000000000..0d5e0117ed --- /dev/null +++ b/npm/ng-packs/packages/schematics/src/commands/ai-config/schema.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json-schema.org/schema", + "$id": "SchematicsABPAiConfig", + "title": "ABP AI Configuration Generator Schema", + "type": "object", + "properties": { + "tool": { + "description": "Comma-separated list of AI tools (e.g., claude,cursor,gemini)", + "type": "string", + "x-prompt": { + "message": "Which AI tools would you like to generate configuration files for? (comma-separated)", + "type": "input" + } + }, + "targetProject": { + "description": "The target project name to generate AI configuration files for", + "type": "string", + "x-prompt": { + "message": "Which project would you like to generate AI config for?", + "type": "input" + } + }, + "overwrite": { + "description": "Overwrite existing AI configuration files", + "type": "boolean", + "default": false + } + }, + "required": [] +} diff --git a/npm/ng-packs/scripts/build-schematics.ts b/npm/ng-packs/scripts/build-schematics.ts index c953a362ca..bdf2e66392 100644 --- a/npm/ng-packs/scripts/build-schematics.ts +++ b/npm/ng-packs/scripts/build-schematics.ts @@ -22,6 +22,8 @@ const PACKAGE_TO_BUILD = 'schematics'; const FILES_TO_COPY_AFTER_BUILD: (FileCopy | string)[] = [ { src: 'src/commands/create-lib/schema.json', dest: 'commands/create-lib/schema.json' }, { src: 'src/commands/change-theme/schema.json', dest: 'commands/change-theme/schema.json' }, + { src: 'src/commands/ai-config/schema.json', dest: 'commands/ai-config/schema.json' }, + { src: 'src/commands/ai-config/files', dest: 'commands/ai-config/files' }, { src: 'src/commands/create-lib/files-package', dest: 'commands/create-lib/files-package' }, { src: 'src/commands/create-lib/files-package-standalone', dest: 'commands/create-lib/files-package-standalone' }, { diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs index 86c8803963..151f57de6c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server.Mongo/MyProjectNameModule.cs @@ -3,7 +3,7 @@ using Blazorise.Icons.FontAwesome; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.Server.Mongo.Components; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs index 762ca3b7b1..8bf5f371fe 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameModule.cs @@ -3,7 +3,7 @@ using Blazorise.Icons.FontAwesome; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.Server.Components; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs index 42ad99abd1..4985e565ba 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server.Mongo/MyProjectNameHostModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.Components; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs index f77a4069e1..c4dade54cc 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Blazor.WebAssembly/Server/MyProjectNameHostModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.Components; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs index 93a9bd89b6..0da4008f3c 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host.Mongo/MyProjectNameModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using OpenIddict.Validation.AspNetCore; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs index d0bc2944dc..7eaaa5261d 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Host/MyProjectNameModule.cs @@ -2,7 +2,7 @@ using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using OpenIddict.Validation.AspNetCore; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyProjectNameModule.cs index b0331d6144..b8f9a7906a 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc.Mongo/MyProjectNameModule.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.Menus; diff --git a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyProjectNameModule.cs b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyProjectNameModule.cs index 4869ab492e..0657ef6803 100644 --- a/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyProjectNameModule.cs +++ b/templates/app-nolayers/aspnet-core/MyCompanyName.MyProjectName.Mvc/MyProjectNameModule.cs @@ -1,6 +1,6 @@ using Microsoft.AspNetCore.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Data; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.Menus; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs index 4d94c3bde9..325ee6805b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server.Tiered/MyProjectNameBlazorModule.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.Server.Tiered.Components; using MyCompanyName.MyProjectName.Blazor.Server.Tiered.Menus; using MyCompanyName.MyProjectName.Localization; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs index 5d27bb122f..658d6d80ca 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.Server/MyProjectNameBlazorModule.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.Server.Components; using MyCompanyName.MyProjectName.Blazor.Server.Menus; using MyCompanyName.MyProjectName.EntityFrameworkCore; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs index 0849b09d6d..2a31f2a763 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp.Tiered/MyProjectNameBlazorModule.cs @@ -14,7 +14,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Client.Menus; using MyCompanyName.MyProjectName.Blazor.WebApp.Tiered.Components; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs index 6a75e85ae0..3a7b435244 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Blazor.WebApp/MyProjectNameBlazorModule.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.WebApp.Client; using MyCompanyName.MyProjectName.Blazor.WebApp.Client.Menus; using MyCompanyName.MyProjectName.Blazor.WebApp.Components; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 73033bdda1..f8e42b82c6 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -15,7 +15,7 @@ using Microsoft.Extensions.Hosting; using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.MultiTenancy; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Mvc; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs index 9d28180208..66b658f09b 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.HttpApi.HostWithIds/MyProjectNameHttpApiHostModule.cs @@ -12,7 +12,7 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite; using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonXLite.Bundling; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using OpenIddict.Validation.AspNetCore; using Volo.Abp; using Volo.Abp.Account; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs index 152076d235..1c7badcaf1 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebModule.cs @@ -14,7 +14,7 @@ using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; using MyCompanyName.MyProjectName.Web.Menus; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.OpenIdConnect; using Volo.Abp.AspNetCore.Mvc.Client; diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs index 27f8f93367..155f08b603 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Web/MyProjectNameWebModule.cs @@ -10,7 +10,7 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.Localization; using MyCompanyName.MyProjectName.MultiTenancy; using MyCompanyName.MyProjectName.Web.Menus; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using OpenIddict.Validation.AspNetCore; using Volo.Abp; using Volo.Abp.Account.Web; diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs index feb60f2b34..6da496bac6 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.AuthServer/MyProjectNameAuthServerModule.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using MyCompanyName.MyProjectName.MultiTenancy; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using OpenIddict.Validation.AspNetCore; using Volo.Abp; using Volo.Abp.Account; diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs index b845e23241..452eb58b56 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Blazor.Server.Host/MyProjectNameBlazorHostModule.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Options; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using MyCompanyName.MyProjectName.Blazor.Server.Host.Components; using MyCompanyName.MyProjectName.Blazor.Server.Host.Menus; using MyCompanyName.MyProjectName.EntityFrameworkCore; diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs index 61534b55c8..dad13a4516 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.HttpApi.Host/MyProjectNameHttpApiHostModule.cs @@ -13,7 +13,7 @@ using Microsoft.Extensions.Hosting; using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.MultiTenancy; using StackExchange.Redis; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Volo.Abp; using Volo.Abp.AspNetCore.Authentication.JwtBearer; using Volo.Abp.AspNetCore.Mvc.UI.MultiTenancy; diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs index 8d912bcad4..35bc9dfaae 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Host/MyProjectNameWebHostModule.cs @@ -2,7 +2,7 @@ using System; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using System.IO; using System.Reflection; using System.Threading.Tasks; diff --git a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs index 5bca5679e1..1612d7b95a 100644 --- a/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs +++ b/templates/module/aspnet-core/host/MyCompanyName.MyProjectName.Web.Unified/MyProjectNameWebUnifiedModule.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Hosting; using MyCompanyName.MyProjectName.EntityFrameworkCore; using MyCompanyName.MyProjectName.MultiTenancy; using MyCompanyName.MyProjectName.Web; -using Microsoft.OpenApi.Models; +using Microsoft.OpenApi; using Swashbuckle.AspNetCore.Swagger; using Volo.Abp; using Volo.Abp.Account;