From 058b55f4fa831502360f0f10ce2c67ec950f6c15 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Sat, 4 Apr 2026 00:11:31 +0330 Subject: [PATCH] Add Required Stuffs to running Project on net8.0 ... --- Base/XIBaseV1EntityController.cs | 120 +++++++ Controllers/StartupController.cs | 2 +- Controllers/V1/Entities/TestsController.cs | 326 ++++++++++++++++++ Data/Configurations/XAiApiDbSeederConfig.cs | 10 + Data/Constants/ConfigurationNodeNames.cs | 7 + Data/Events/XTestEvents.cs | 9 + Data/Extensions/XAiApiDbSeederExtension.cs | 67 ++++ Data/GraphQL/XTestGraphQLTypeHelper.cs | 25 ++ Data/GraphQL/XTestGraphQuery.cs | 22 ++ Data/GraphQL/XTestGraphSchema.cs | 13 + Data/GraphQL/XTestGraphType.cs | 13 + Data/Helpers/XAiApiDataHelperGraphQLHelper.cs | 71 ++++ Data/Helpers/XAiApiDataProviderHelper.cs | 199 +++++++++++ Data/Interfaces/IXAiApiDbSeederConfig.cs | 7 + Data/Interfaces/IXTestEvents.cs | 8 + Data/Interfaces/IXTestGraphQLTypeHelper.cs | 8 + Data/Interfaces/IXTestRepository.cs | 8 + Data/Models/XTest.cs | 9 + Data/Models/XTestDescriptor.cs | 7 + Data/Repositories/Ef/XTestEfRepository.cs | 37 ++ .../Mongo/XTestMongoRepository.cs | 37 ++ Data/Seeder/XAiApiDbSeeder.cs | 64 ++++ Data/XAiApiDbContext.cs | 28 ++ Push/.gitkeep | 0 Startup.cs | 86 ++++- appsettings.json | 2 +- nuget.config | 17 +- xAiApi.csproj | 3 +- 28 files changed, 1194 insertions(+), 11 deletions(-) create mode 100644 Base/XIBaseV1EntityController.cs create mode 100644 Controllers/V1/Entities/TestsController.cs create mode 100644 Data/Configurations/XAiApiDbSeederConfig.cs create mode 100644 Data/Constants/ConfigurationNodeNames.cs create mode 100644 Data/Events/XTestEvents.cs create mode 100644 Data/Extensions/XAiApiDbSeederExtension.cs create mode 100644 Data/GraphQL/XTestGraphQLTypeHelper.cs create mode 100644 Data/GraphQL/XTestGraphQuery.cs create mode 100644 Data/GraphQL/XTestGraphSchema.cs create mode 100644 Data/GraphQL/XTestGraphType.cs create mode 100644 Data/Helpers/XAiApiDataHelperGraphQLHelper.cs create mode 100644 Data/Helpers/XAiApiDataProviderHelper.cs create mode 100644 Data/Interfaces/IXAiApiDbSeederConfig.cs create mode 100644 Data/Interfaces/IXTestEvents.cs create mode 100644 Data/Interfaces/IXTestGraphQLTypeHelper.cs create mode 100644 Data/Interfaces/IXTestRepository.cs create mode 100644 Data/Models/XTest.cs create mode 100644 Data/Models/XTestDescriptor.cs create mode 100644 Data/Repositories/Ef/XTestEfRepository.cs create mode 100644 Data/Repositories/Mongo/XTestMongoRepository.cs create mode 100644 Data/Seeder/XAiApiDbSeeder.cs create mode 100644 Data/XAiApiDbContext.cs create mode 100644 Push/.gitkeep diff --git a/Base/XIBaseV1EntityController.cs b/Base/XIBaseV1EntityController.cs new file mode 100644 index 0000000..d53bec7 --- /dev/null +++ b/Base/XIBaseV1EntityController.cs @@ -0,0 +1,120 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using xCommons.Attributes; +using xCommons.Configurations; +using xCommons.Extensions; +using xCommons.Providers; +using xDataService.Interfaces; +using xIdentityService.Controllers; +using xIdentityService.Interfaces; +using xModels.Base; +using xPushService.Base; +using xPushService.Constants; + +namespace xAiApi.Base +{ + [ApiController] + [ApiVersion("1.0")] + [RequireXPowered(true)] + [Route("api/v{version:apiVersion}/entities/[controller]")] + public abstract class XIBaseV1EntityController : XIBaseEntityController + where TEntity : XBaseEntity + { + // + #region Constructor ... + protected XIBaseV1EntityController( + ILogger> logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXBaseRepository repository + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + repository + ) + { } + #endregion + } + + public abstract class XIBaseV1EntityHubController : XIBaseV1EntityController + where TEntity : XBaseEntity + { + // + #region Props ... + public IHubContext> Hub { get; } + #endregion + + // + #region Constructor ... + protected XIBaseV1EntityHubController( + ILogger> logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXBaseRepository repository, + IHubContext> hub = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + repository + ) + { + Hub = hub; + } + #endregion + + // + #region Hub ... + [NonAction] + public async Task SendPush( + string action, + string payLoad + ) + { + // + var actions = new List + { + XBaseEntityHubAction.Add.GetStringValue(), + XBaseEntityHubAction.Update.GetStringValue(), + XBaseEntityHubAction.Delete.GetStringValue(), + XBaseEntityHubAction.AddMany.GetStringValue(), + XBaseEntityHubAction.DeleteMany.GetStringValue(), + XBaseEntityHubAction.UpdateMany.GetStringValue(), + XBaseEntityHubAction.AddOrUpdate.GetStringValue(), + }; + + // + // Validate ... + var isValid = + !Hub.IsNull() && + !action.IsNullOrEmpty() && + !payLoad.IsNullOrEmpty() && + actions.Contains(action); + if (!isValid) + { + return; + } + + // + // Retrieve Connection Id ... + var connectionId = GetConnectionId(); + var clients = Hub.Clients.All; + if (!connectionId.IsNullOrEmpty()) + { + clients = Hub.Clients.AllExcept(connectionId); + } + + // + await clients.SendAsync(action, payLoad, connectionId); + } + #endregion + } +} \ No newline at end of file diff --git a/Controllers/StartupController.cs b/Controllers/StartupController.cs index 3717c43..6504238 100644 --- a/Controllers/StartupController.cs +++ b/Controllers/StartupController.cs @@ -36,7 +36,7 @@ namespace xAiApi.Controllers { // var controllerName = GetControllerName(); - var message = $"{AppConfiguration.WelcomeMessage}"; + var message = $"Salam, {AppConfiguration.WelcomeMessage}"; // return Ok(message); diff --git a/Controllers/V1/Entities/TestsController.cs b/Controllers/V1/Entities/TestsController.cs new file mode 100644 index 0000000..1aad41f --- /dev/null +++ b/Controllers/V1/Entities/TestsController.cs @@ -0,0 +1,326 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.SignalR; +using Microsoft.Extensions.Logging; +using xAiApi.Base; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xCommons.Configurations; +using xCommons.Extensions; +using xCommons.Providers; +using xIdentityHelper; +using xIdentityService.Interfaces; +using xModels.Base; +using xModels.Dtos; +using xPushService.Base; +using xPushService.Constants; + +namespace xAiApi.Controllers.V1.Entities +{ + /// + /// Simple XTest Entity Controller ... + /// + public class TestsController : XIBaseV1EntityHubController + { + // + #region Constructor ... + public TestsController( + ILogger logger, + XAppConfiguration appConfiguration, + IXIdentityProvider identityProvider, + XValidationProvider validationProvider, + IXTestRepository repository, + IHubContext> hub = null + ) : base( + logger, + appConfiguration, + identityProvider, + validationProvider, + repository, + hub + ) + { } + #endregion + + // + #region Interface Implementations ... + // + #region Retrieve ... + [HttpGet("{id}")] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task> Get( + [FromRoute] int id, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false + ) + { + return await base + .Get( + id: id, + containsDetail: containsDetail, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + + [HttpGet] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task>> GetAll( + [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false + ) + { + return await base + .GetAll( + containsDetail: containsDetail, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + + [HttpGet("FindOne/{query}")] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task> FindOne( + [FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false + ) + { + return await base + .FindOne( + query: query, + containsDetail: containsDetail, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + + [HttpGet("FindMany/{query}")] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task>> FindMany( + [FromRoute] string query, [FromQuery] bool ignoreSoftDeleteds = true, [FromQuery] bool containsDetail = false + ) + { + return await base + .FindMany( + query: query, + containsDetail: containsDetail, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + + [HttpGet("Query")] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task>> Query( + [FromQuery] XQuery query, [FromQuery] bool ignoreSoftDeleteds = true + ) + { + return await base + .Query( + query: query, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + #endregion + + // + #region Add ... + [HttpPost] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task> Add( + [FromBody] XTest item + ) + { + // + var entity = await base + .Add(item); + + // + // Handle Sending Push Notification ... + if (!entity.IsNullOrDefault()) + { + // + await SendPush( + action: XBaseEntityHubAction.Add.GetStringValue(), + payLoad: entity.ToJSON() + ); + } + + // + return entity; + } + + [HttpPost("AddOrUpdate")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task> AddOrUpdate( + [FromBody] XTest item + ) + { + // + var entity = await base + .AddOrUpdate(item); + + // + // Handle Sending Push Notification ... + if (!entity.IsNullOrDefault()) + { + // + await SendPush( + action: XBaseEntityHubAction.AddOrUpdate.GetStringValue(), + payLoad: entity.ToJSON() + ); + } + + // + return entity; + } + + [HttpPost("AddMany")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task AddMany( + [FromBody] XBaseRangeRequest request + ) + { + // + var result = await base + .AddMany(request); + + // + if (!(result as OkObjectResult).IsNull()) + { + // + await SendPush( + action: XBaseEntityHubAction.AddMany.GetStringValue(), + payLoad: request.Items.ToJSON() + ); + } + + // + return result; + } + #endregion + + // + #region Update ... + [HttpPut("{id}")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task> Update( + [FromRoute] int id, [FromBody] XTest item + ) + { + // + var entity = await base + .Update( + id, + item + ); + + // + if (!entity.IsNullOrDefault()) + { + // + await SendPush( + action: XBaseEntityHubAction.Update.GetStringValue(), + payLoad: entity.ToJSON() + ); + } + + // + return entity; + } + + [HttpPost("UpdateMany")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task> UpdateMany( + [FromBody] XBaseRangeRequest request + ) + { + // + var result = await base + .UpdateMany(request); + + // + var resultObject = (result.Result as OkObjectResult).Value; + if (!resultObject.IsNull() && (bool)resultObject) + { + // + await SendPush( + action: XBaseEntityHubAction.UpdateMany.GetStringValue(), + payLoad: request.Items.ToJSON() + ); + } + + // + return result; + } + #endregion + + // + #region Exists ... + [HttpGet("{id}/IsExists")] + [Authorize(Policy = XPolicies.EnabledUser)] + public override async Task> IsExists( + [FromRoute] int id, [FromQuery] bool ignoreSoftDeleteds = true + ) + { + return await base + .IsExists( + id: id, + ignoreSoftDeleteds: ignoreSoftDeleteds + ); + } + #endregion + + // + #region Remove ... + [HttpDelete("{id}")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task> Remove( + [FromRoute] int id, bool softDelete = true + ) + { + // + var entity = await base + .Remove( + id: id, + softDelete: softDelete + ); + + // + if (!entity.IsNullOrDefault()) + { + // + await SendPush( + action: XBaseEntityHubAction.Delete.GetStringValue(), + payLoad: entity.ToJSON() + ); + } + + // + return entity; + } + + [HttpPost("RemoveMany")] + [Authorize(Policy = XPolicies.EnabledAdminOrAgent)] + public override async Task RemoveMany( + [FromBody] XBaseRangeRequest request, bool softDelete = true + ) + { + // + var result = await base + .RemoveMany( + request: request, + softDelete: softDelete + ); + + // + if (!(result as OkObjectResult).IsNull()) + { + // + await SendPush( + action: XBaseEntityHubAction.DeleteMany.GetStringValue(), + payLoad: request.Items.ToJSON() + ); + } + + // + return result; + } + #endregion + #endregion + } +} \ No newline at end of file diff --git a/Data/Configurations/XAiApiDbSeederConfig.cs b/Data/Configurations/XAiApiDbSeederConfig.cs new file mode 100644 index 0000000..680c173 --- /dev/null +++ b/Data/Configurations/XAiApiDbSeederConfig.cs @@ -0,0 +1,10 @@ +using xAiApi.Data.Interfaces; +using xDataService.Interfaces; + +namespace xAiApi.Data.Configurations +{ + public class XAiApiDbSeederConfig : IXAiApiDbSeederConfig, IXDbSeederConfig + { + public bool UpdateExists { get; set; } + } +} \ No newline at end of file diff --git a/Data/Constants/ConfigurationNodeNames.cs b/Data/Constants/ConfigurationNodeNames.cs new file mode 100644 index 0000000..1e7b9ec --- /dev/null +++ b/Data/Constants/ConfigurationNodeNames.cs @@ -0,0 +1,7 @@ +namespace xAiApi.Data.Constants +{ + public partial struct ConfigurationNodeNames + { + public const string DATA_SERVICE_DB_SEED_NODE = "DbSeeder"; + } +} \ No newline at end of file diff --git a/Data/Events/XTestEvents.cs b/Data/Events/XTestEvents.cs new file mode 100644 index 0000000..7f84c0d --- /dev/null +++ b/Data/Events/XTestEvents.cs @@ -0,0 +1,9 @@ +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Events; + +namespace xAiApi.Data.Events +{ + public class XTestEvents : XBaseRepositoryEvents, IXTestEvents + { } +} \ No newline at end of file diff --git a/Data/Extensions/XAiApiDbSeederExtension.cs b/Data/Extensions/XAiApiDbSeederExtension.cs new file mode 100644 index 0000000..8e0dbfa --- /dev/null +++ b/Data/Extensions/XAiApiDbSeederExtension.cs @@ -0,0 +1,67 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using xAiApi.Data.Configurations; +using xAiApi.Data.Constants; +using xAiApi.Data.Interfaces; +using xCommons.Extensions; + +namespace xAiApi.Data.Extensions +{ + public static class XAiApiDbSeederExtension + { + /// + /// Extract XDbSeeder Configurations From IConfiguration + /// + /// + /// + public static XAiApiDbSeederConfig GetXDbSeederConfiguration( + this IConfiguration configuration + ) + { + // + var xDbSeederConfigSection = configuration.GetSection(ConfigurationNodeNames.DATA_SERVICE_DB_SEED_NODE); + return xDbSeederConfigSection.Get(); + } + + /// + /// Register XDbSeeder Configurations on DI + /// + /// + /// + public static void AddXDbSeederConfiguration( + this IServiceCollection services, + IConfiguration configuration + ) + { + // + var dbSeederConfig = configuration.GetXDbSeederConfiguration(); + if (dbSeederConfig.IsNull()) + { + return; + } + + // + services.AddSingleton(dbSeederConfig); + } + + /// + /// Register XDbSeeder Configurations on DI + /// + /// + /// + public static void AddXDbSeederConfiguration( + this IServiceCollection services, + XAiApiDbSeederConfig configuration + ) + { + // + if (configuration.IsNull()) + { + return; + } + + // + services.AddSingleton(configuration); + } + } +} \ No newline at end of file diff --git a/Data/GraphQL/XTestGraphQLTypeHelper.cs b/Data/GraphQL/XTestGraphQLTypeHelper.cs new file mode 100644 index 0000000..f2a0ed7 --- /dev/null +++ b/Data/GraphQL/XTestGraphQLTypeHelper.cs @@ -0,0 +1,25 @@ +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.GraphQL; + +namespace xAiApi.Data.GraphQL +{ + public class XTestGraphQLTypeHelper : XBaseGraphQLTypeHelper, IXTestGraphQLTypeHelper + { + public XTestGraphQLTypeHelper( + XDataServiceConfiguration configuration + ) : base(configuration) + { } + + public override string GetInQueryCollectionName() + { + return "tests"; + } + + public override string GetInQuerySingleName() + { + return "test"; + } + } +} \ No newline at end of file diff --git a/Data/GraphQL/XTestGraphQuery.cs b/Data/GraphQL/XTestGraphQuery.cs new file mode 100644 index 0000000..4746e79 --- /dev/null +++ b/Data/GraphQL/XTestGraphQuery.cs @@ -0,0 +1,22 @@ +using GraphQL.Types; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.GraphQL; + +namespace xAiApi.Data.GraphQL +{ + public class XTestGraphQuery : XBaseGraphQLQuery + { + public XTestGraphQuery( + XDataServiceConfiguration configuration, + IXTestRepository repository, + IXTestGraphQLTypeHelper helper + ) : base( + configuration, + repository, + helper + ) + { } + } +} \ No newline at end of file diff --git a/Data/GraphQL/XTestGraphSchema.cs b/Data/GraphQL/XTestGraphSchema.cs new file mode 100644 index 0000000..4ca0d42 --- /dev/null +++ b/Data/GraphQL/XTestGraphSchema.cs @@ -0,0 +1,13 @@ +using System; +using GraphQL.Types; + +namespace xAiApi.Data.GraphQL +{ + public class XTestGraphSchema : Schema + { + public XTestGraphSchema(IServiceProvider services) : base(services) + { + Query = (XTestGraphQuery)services.GetService(typeof(XTestGraphQuery)); + } + } +} \ No newline at end of file diff --git a/Data/GraphQL/XTestGraphType.cs b/Data/GraphQL/XTestGraphType.cs new file mode 100644 index 0000000..7ceb343 --- /dev/null +++ b/Data/GraphQL/XTestGraphType.cs @@ -0,0 +1,13 @@ +using xAiApi.Data.Models.Entities; +using xDataService.GraphQL; + +namespace xAiApi.Data.GraphQL +{ + public class XTestGraphType : XBaseGraphObjectType + { + public XTestGraphType() : base() + { + Field(x => x.Title); + } + } +} \ No newline at end of file diff --git a/Data/Helpers/XAiApiDataHelperGraphQLHelper.cs b/Data/Helpers/XAiApiDataHelperGraphQLHelper.cs new file mode 100644 index 0000000..dfbd292 --- /dev/null +++ b/Data/Helpers/XAiApiDataHelperGraphQLHelper.cs @@ -0,0 +1,71 @@ +using GraphQL.Server; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.DependencyInjection; +using xAiApi.Data.GraphQL; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.GraphQL; +using xDataService.Interfaces; + +namespace xAiApi.Data.Helpers +{ + public class XAiApiDataHelperGraphQLHelper : IXGraphQLHelper + { + public void AddXGraphEnumTypes(IServiceCollection services) { } + + public void AddXGraphInputTypes(IServiceCollection services) { } + + public void AddXGraphMutations(IServiceCollection services) { } + + public void AddXGraphObjectTypes(IServiceCollection services) + { + // + // XTest ... + services.AddSingleton(); + services.AddSingleton>(); + } + + public void AddXGraphQueries(IServiceCollection services) + { + // + // XTest ... + services.AddSingleton(); + services.AddScoped(); + } + + public void AddXGraphSchemas(IServiceCollection services) + { + // + services.AddScoped(); + } + + public void AddXGraphSubscriptions(IServiceCollection services) { } + + public IGraphQLBuilder AddXGraphTypes(IGraphQLBuilder builder) + { + // + builder.AddGraphTypes(typeof(XTestGraphSchema)); + + // + return builder; + } + + public void UseXGraph(IApplicationBuilder app) + { + // + using (var scope = app.ApplicationServices.CreateScope()) + { + // + // XDataServiceConfiguration ... + var dataServiceConfiguration = scope.ServiceProvider.GetService(); + + // + // XTest ... + var testHelper = scope.ServiceProvider.GetService(); + app.UseGraphQL(testHelper.GetGraphQLPath()); + app.UseGraphQLWebSockets(); + } + } + } +} \ No newline at end of file diff --git a/Data/Helpers/XAiApiDataProviderHelper.cs b/Data/Helpers/XAiApiDataProviderHelper.cs new file mode 100644 index 0000000..178ccbf --- /dev/null +++ b/Data/Helpers/XAiApiDataProviderHelper.cs @@ -0,0 +1,199 @@ +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using MongoDB.Bson.Serialization.Conventions; +using xAiApi.Data.Events; +using xAiApi.Data.Extensions; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xAiApi.Data.Repositories.Ef; +using xAiApi.Data.Repositories.Mongo; +using xAiApi.Data.Seeder; +using xCommons.Extensions; +using xDataService.Configuration; +using xDataService.Constants; +using xDataService.Interfaces; +using xDataService.Providers; +using xExceptions.Constants; + +namespace xAiApi.Data.Helpers +{ + public class XAiApiDataProviderHelper : IXDataServiceHelper + { + // + private readonly ILogger logger; + + // + public XAiApiDataProviderHelper(ILogger logger) + { + this.logger = logger; + } + + // + #region Actions ... + public void AddDbContext( + IServiceCollection services, + string connectionString, + XDbProviders dbProvider, + ServiceLifetime lifetime, + Action optionsBuilder = null + ) + { + // + logger.LogInformation("Start AddDbContext ..."); + + // + switch (dbProvider) + { + // + case XDbProviders.MySQL: + // + services.AddDbContext(cfg => + { + cfg.UseMySQL(connectionString, optionsBuilder); + }, lifetime); + break; + + // + case XDbProviders.SQLite: + // + services.AddDbContext(cfg => + { + cfg.UseSqlite(connectionString, optionsBuilder); + }, lifetime); + break; + + // + case XDbProviders.SQLServer: + // + services.AddDbContext(cfg => + { + cfg.UseSqlServer(connectionString, optionsBuilder); + }, lifetime); + break; + + // + case XDbProviders.MongoDB: + break; + + // + default: + Console.WriteLine("Unsuported Data Provider Type ..."); + XException.NotAllowed.Throw(); + break; + } + + // + logger.LogInformation("End AddDbContext ..."); + } + + public void AddRepositories( + IServiceCollection services, + ServiceLifetime lifetime + ) + { + // + logger.LogInformation("Start AddRepositories ..."); + + // + var dataServiceConfiguration = services.GetRegisteredService(); + + // + #region Events ... + // + // XTest ... + services.Add(new ServiceDescriptor(typeof(IXTestEvents), typeof(XTestEvents), ServiceLifetime.Singleton)); + #endregion + + // + #region Repositories ... + // + // Adding DbContext if EFCore ... + switch (dataServiceConfiguration.Provider) + { + // + case XDbProviders.MySQL: + case XDbProviders.SQLite: + case XDbProviders.SQLServer: + // + // XTest ... + services.Add(new ServiceDescriptor(typeof(IXTestRepository), typeof(XTestEfRepository), lifetime)); + break; + + // + case XDbProviders.MongoDB: + // + // XTest ... + services.Add(new ServiceDescriptor(typeof(IXTestRepository), typeof(XTestMongoRepository), lifetime)); + break; + + // + default: + Console.WriteLine("Unsuported Data Provider Type ..."); + XException.NotAllowed.Throw(); + break; + } + #endregion + + // + logger.LogInformation("End AddRepositories ..."); + } + + public void AddKeyGenerators(IServiceCollection services) + { + // + services.AddSingleton, XIntKeyGenerator>(); + } + + public void AddDbSeederConfiguration( + IServiceCollection services, + IConfiguration configuration + ) + { + // + logger.LogInformation("Start AddDbSeederConfiguration ..."); + + // + // Retrieve Config from appSettings ... + var dbSeederConfig = configuration.GetXDbSeederConfiguration(); + if (!dbSeederConfig.IsNull()) + { + services.AddXDbSeederConfiguration(dbSeederConfig); + } + + // + logger.LogInformation("End AddDbSeederConfiguration ..."); + } + + public void AddDbSeeder( + IServiceCollection services, + IConfiguration config, + ServiceLifetime lifetime + ) where TDbSeeder : IXDbSeeder + { + // + logger.LogInformation("Start AddDbSeeder ..."); + + // + // Adding DbSeeder ... + services.Add(new ServiceDescriptor(typeof(IXDbSeeder), typeof(XAiApiDbSeeder), lifetime)); + + // + logger.LogInformation("End AddDbSeeder ..."); + } + + public ConventionPack MongoConventionPacks() + { + return null; + } + + public void RegisterMongoExtras() { } + #endregion + + // + #region Private ... + #endregion + } +} \ No newline at end of file diff --git a/Data/Interfaces/IXAiApiDbSeederConfig.cs b/Data/Interfaces/IXAiApiDbSeederConfig.cs new file mode 100644 index 0000000..210b882 --- /dev/null +++ b/Data/Interfaces/IXAiApiDbSeederConfig.cs @@ -0,0 +1,7 @@ +using xDataService.Interfaces; + +namespace xAiApi.Data.Interfaces +{ + public interface IXAiApiDbSeederConfig : IXDbSeederConfig + { } +} \ No newline at end of file diff --git a/Data/Interfaces/IXTestEvents.cs b/Data/Interfaces/IXTestEvents.cs new file mode 100644 index 0000000..a14cf65 --- /dev/null +++ b/Data/Interfaces/IXTestEvents.cs @@ -0,0 +1,8 @@ +using xAiApi.Data.Models.Entities; +using xDataService.Interfaces; + +namespace xAiApi.Data.Interfaces +{ + public interface IXTestEvents : IXBaseRepositoryEvents + { } +} \ No newline at end of file diff --git a/Data/Interfaces/IXTestGraphQLTypeHelper.cs b/Data/Interfaces/IXTestGraphQLTypeHelper.cs new file mode 100644 index 0000000..83b5cb0 --- /dev/null +++ b/Data/Interfaces/IXTestGraphQLTypeHelper.cs @@ -0,0 +1,8 @@ +using xAiApi.Data.Models.Entities; +using xDataService.Interfaces; + +namespace xAiApi.Data.Interfaces +{ + public interface IXTestGraphQLTypeHelper : IXBaseGraphQLTypeHelper + { } +} \ No newline at end of file diff --git a/Data/Interfaces/IXTestRepository.cs b/Data/Interfaces/IXTestRepository.cs new file mode 100644 index 0000000..d14df12 --- /dev/null +++ b/Data/Interfaces/IXTestRepository.cs @@ -0,0 +1,8 @@ +using xAiApi.Data.Models.Entities; +using xDataService.Interfaces; + +namespace xAiApi.Data.Interfaces +{ + public interface IXTestRepository : IXBaseRepository + { } +} \ No newline at end of file diff --git a/Data/Models/XTest.cs b/Data/Models/XTest.cs new file mode 100644 index 0000000..44a3830 --- /dev/null +++ b/Data/Models/XTest.cs @@ -0,0 +1,9 @@ +using xModels.Base; + +namespace xAiApi.Data.Models.Entities +{ + public class XTest : XBaseIntIDEntity + { + public string Title { get; set; } + } +} \ No newline at end of file diff --git a/Data/Models/XTestDescriptor.cs b/Data/Models/XTestDescriptor.cs new file mode 100644 index 0000000..6786ad0 --- /dev/null +++ b/Data/Models/XTestDescriptor.cs @@ -0,0 +1,7 @@ +namespace xAiApi.Data.Models +{ + public class XTestDescriptor + { + public string Title { get; set; } + } +} \ No newline at end of file diff --git a/Data/Repositories/Ef/XTestEfRepository.cs b/Data/Repositories/Ef/XTestEfRepository.cs new file mode 100644 index 0000000..a639e78 --- /dev/null +++ b/Data/Repositories/Ef/XTestEfRepository.cs @@ -0,0 +1,37 @@ +using System.Linq; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.Db; +using xDataService.EFRepositories; +using xDataService.Interfaces; + +namespace xAiApi.Data.Repositories.Ef +{ + public class XTestEfRepository : XBaseEFRepository, IXTestRepository + where TDbContext : XDbContext + { + // + public XTestEfRepository( + IXUnitOfWorks unitOfWorks, + XDataServiceConfiguration configuration, + IXKeyGenerator keyGenerator = null, + IXBaseRepositoryEvents baseRepositoryEvents = null + ) : base( + unitOfWorks, + configuration, + keyGenerator, + baseRepositoryEvents + ) + { } + + public override IQueryable GetFullDbSet() + { + return dbSet; + } + + // + #region Special ... + #endregion + } +} \ No newline at end of file diff --git a/Data/Repositories/Mongo/XTestMongoRepository.cs b/Data/Repositories/Mongo/XTestMongoRepository.cs new file mode 100644 index 0000000..05f770e --- /dev/null +++ b/Data/Repositories/Mongo/XTestMongoRepository.cs @@ -0,0 +1,37 @@ +using MongoDB.Driver; +using MongoDB.Driver.Linq; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.Interfaces; +using xDataService.MongoRepositories; + +namespace xAiApi.Data.Repositories.Mongo +{ + public class XTestMongoRepository : XBaseMongoRepository, IXTestRepository + { + // + public XTestMongoRepository( + XDataServiceConfiguration configuration, + string collectionName = null, + IXKeyGenerator keyGenerator = null, + IXBaseRepositoryEvents baseRepositoryEvents = null + ) : base( + configuration, + collectionName, + keyGenerator, + baseRepositoryEvents + ) + { } + + public override IMongoQueryable GetFullDbSet() + { + return collection + .AsQueryable(); + } + + // + #region Special ... + #endregion + } +} \ No newline at end of file diff --git a/Data/Seeder/XAiApiDbSeeder.cs b/Data/Seeder/XAiApiDbSeeder.cs new file mode 100644 index 0000000..861d10d --- /dev/null +++ b/Data/Seeder/XAiApiDbSeeder.cs @@ -0,0 +1,64 @@ +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using xAiApi.Data.Interfaces; +using xAiApi.Data.Models; +using xCommons.Extensions; +using xDataService.Configuration; +using xDataService.Interfaces; + +namespace xAiApi.Data.Seeder +{ + public class XAiApiDbSeeder : IXDbSeeder + { + // + public IXDbSeederConfig Config { get; } + public readonly IXAiApiDbSeederConfig config; + private readonly ILogger logger; + private readonly IXTestRepository testsRepository; + public XDataServiceConfiguration DataServiceConfiguration { get; } + + // + public XAiApiDbSeeder( + ILogger logger, + IXTestRepository testsRepository, + IXAiApiDbSeederConfig config = null, + XDataServiceConfiguration dataServiceConfiguration = null + ) + { + Config = config; + this.config = config; + this.logger = logger; + this.testsRepository = testsRepository; + DataServiceConfiguration = dataServiceConfiguration; + } + + public async Task Seed() + { + // + // TODO: Do any additional Seeding ... + try + { + // + // Check Configuration Exists ... + if (config.IsNull()) + { + logger.LogInformation($"there is no Configured Objects to Seed ..."); + } + else + { + } + } + catch (Exception ex) + { + logger.LogError($"Failed Seeding: {ex.Message} ..."); + } + } + + // + #region Private ... + private async Task SeedTest(XTestDescriptor dTests) + { } + #endregion + } +} \ No newline at end of file diff --git a/Data/XAiApiDbContext.cs b/Data/XAiApiDbContext.cs new file mode 100644 index 0000000..9e7ba01 --- /dev/null +++ b/Data/XAiApiDbContext.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore; +using xAiApi.Data.Models.Entities; +using xDataService.Configuration; +using xDataService.Db; + +namespace xAiApi.Data +{ + public partial class XAiApiDbContext : XDbContext + { + // + #region DbSets ... + public DbSet Tests { get; set; } + #endregion + + // + #region Navigation Property Entities ... + #endregion + + public XAiApiDbContext( + DbContextOptions options, + XDataServiceConfiguration config + ) : base(options, config) { } + + public override void OnXConfiguring(DbContextOptionsBuilder optionsBuilder) { } + + public override void OnXModelCreating(ModelBuilder modelBuilder) { } + } +} \ No newline at end of file diff --git a/Push/.gitkeep b/Push/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Startup.cs b/Startup.cs index a345b17..294ce8f 100644 --- a/Startup.cs +++ b/Startup.cs @@ -24,6 +24,9 @@ using xDataService.Interfaces; using xPushService.Helpers; using xAiApi.Extensions; using xAiApi.DI; +using xAiApi.Data.Helpers; +using xAiApi.Data; +using xAiApi.Data.Seeder; // using xApi.Extensions; // using xDataHelper; // using xDataHelper.DbSeeder; @@ -123,6 +126,81 @@ namespace xAiApi // // Register XIdentityService ... services.AddXIdentityService(Configuration, lifeTime); + + // + // Register DataService here ... + #region Register xDataService ... + // + // Register IXDataServiceHelper ... + services.AddSingleton(); + + // + // Prepare Db Options Builder based on Provider ... + var providerType = Configuration.GetXDbProviderType(); + switch (providerType) + { + // + case XDbProviders.MySQL: + case XDbProviders.SQLite: + case XDbProviders.SQLServer: + Action optionsBuilder = optionsBuilder = b => + { + b.MigrationsAssembly(typeof(Startup).GetTypeInfo().Assembly.GetName().Name); + }; + + // + // Register xDataService on DI ... + services.AddXDataService( + Configuration, + lifeTime, + XDbProviderConfigurations.DEFAULT_CONNECTION_NAME, + optionsBuilder + ); + break; + + // + case XDbProviders.MongoDB: + // + // Register xDataService on DI ... + services.AddXDataService( + Configuration, + lifeTime, + XDbProviderConfigurations.DEFAULT_CONNECTION_NAME + ); + break; + } + #endregion + + // + // Register GraphQL here ... + #region Register xGraphQL ... + // + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + // + services.Configure(options => + { + options.AllowSynchronousIO = true; + }); + + // + // Register XGraphQL Helper ... + services.AddSingleton(); + + // + services.AddXGraphQL(options => + { + // + options.EnableMetrics = true; + options.UnhandledExceptionDelegate = context => + { + Console.WriteLine("XGraphQL Error: " + context.OriginalException.Message); + }; + }); + #endregion } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) @@ -166,7 +244,7 @@ namespace xAiApi // #region XPushService ... // - var helper = new XPushServiceHelper(); + // var helper = new XPushServiceHelper(); // // helper.AddHub("termsHub"); @@ -175,17 +253,13 @@ namespace xAiApi // helper.AddHub("stringEntityHub"); // - app.UseXPushService(helper); + // app.UseXPushService(helper); #endregion // // Use xDataService Middleware ... app.UseXDataService(); - // // - // // Using Services ... - // app.UseXServices(); - // // Use xGraphQL Middleware ... app.UseXGraphQL(withPlayground: withPlayground); diff --git a/appsettings.json b/appsettings.json index fbb55a3..1b90dcf 100644 --- a/appsettings.json +++ b/appsettings.json @@ -13,7 +13,7 @@ "SwaggerConfiguration": { "Version": "v1.0", "Title": "xSaherElm AI API", - "Description": "Complete API Documentation", + "Description": "Complete AI API Documentation", "Contact": { "Name": "Hadi Khazaee Asl", "Email": "hadi_khazaee_asl@yahoo.com", diff --git a/nuget.config b/nuget.config index 461a288..fec1fa5 100644 --- a/nuget.config +++ b/nuget.config @@ -1,8 +1,21 @@ - + - + + + + + + + + + \ No newline at end of file diff --git a/xAiApi.csproj b/xAiApi.csproj index 6e01616..b6fa669 100644 --- a/xAiApi.csproj +++ b/xAiApi.csproj @@ -1,7 +1,7 @@ - netcoreapp3.1 + net8.0 xSaherElm.xAiApi 1.0.0 Hadi Khazaee Asl @@ -29,6 +29,7 @@ +