netcore-blueprint 0.0.16 → 0.0.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Modules/ItemModule/ItemModule.API/Controllers/Public/ItemController.cs +65 -0
- package/Modules/ItemModule/ItemModule.API/ItemModule.API.csproj +27 -0
- package/Modules/ItemModule/ItemModule.API/ItemModule.cs +24 -0
- package/Modules/ItemModule/ItemModule.API/Mappers/DtoItemMappingProfile.cs +26 -0
- package/Modules/ItemModule/ItemModule.Core/Dtos/Admin/ItemRequestDto.cs +8 -0
- package/Modules/ItemModule/ItemModule.Core/Dtos/Admin/ItemResponseDto.cs +8 -0
- package/Modules/ItemModule/ItemModule.Core/Entities/Item.cs +8 -0
- package/Modules/ItemModule/ItemModule.Core/Interfaces/API/IItemService.cs +9 -0
- package/Modules/ItemModule/ItemModule.Core/Interfaces/SPI/IItemInfra.cs +9 -0
- package/Modules/ItemModule/ItemModule.Core/ItemCoreDependencyInjection.cs +19 -0
- package/Modules/ItemModule/ItemModule.Core/ItemModule.Core.csproj +18 -0
- package/Modules/ItemModule/ItemModule.Core/Services/ItemService.cs +20 -0
- package/Modules/ItemModule/ItemModule.Infrastructure/Database/ItemConfiguration.cs +22 -0
- package/Modules/ItemModule/ItemModule.Infrastructure/Database/Seeder.cs +21 -0
- package/Modules/ItemModule/ItemModule.Infrastructure/ItemInfraDependencyInjection.cs +21 -0
- package/Modules/ItemModule/ItemModule.Infrastructure/ItemModule.Infrastructure.csproj +14 -0
- package/Modules/ItemModule/ItemModule.Infrastructure/Services/MySQLItemInfra.cs +16 -0
- package/bin/create-module.js +43 -30
- package/package.json +2 -2
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
using AutoMapper;
|
|
2
|
+
using ItemModule.Core.Dtos.Admin;
|
|
3
|
+
using ItemModule.Core.Entities;
|
|
4
|
+
using ItemModule.Core.Interfaces.API;
|
|
5
|
+
using Microsoft.AspNetCore.Http;
|
|
6
|
+
using Microsoft.AspNetCore.Mvc;
|
|
7
|
+
using Microsoft.Extensions.Logging;
|
|
8
|
+
using Shared.Core.Shared.Models;
|
|
9
|
+
using System.Diagnostics;
|
|
10
|
+
|
|
11
|
+
namespace ItemModule.API.Controllers.Public
|
|
12
|
+
{
|
|
13
|
+
/// <summary>
|
|
14
|
+
/// Item Controller
|
|
15
|
+
/// </summary>
|
|
16
|
+
[Route("rest/v{version:apiVersion}/items")]
|
|
17
|
+
[Produces("application/json")]
|
|
18
|
+
[ApiController]
|
|
19
|
+
public class ItemController : Controller
|
|
20
|
+
{
|
|
21
|
+
private readonly IMapper _mapper;
|
|
22
|
+
private ILogger _logger;
|
|
23
|
+
private readonly IItemService _itemService;
|
|
24
|
+
|
|
25
|
+
/// <summary>
|
|
26
|
+
/// Constructor
|
|
27
|
+
/// </summary>
|
|
28
|
+
/// <param name="logger"></param>
|
|
29
|
+
/// <param name="mapper"></param>
|
|
30
|
+
/// <param name="itemService"></param>
|
|
31
|
+
public ItemController(
|
|
32
|
+
ILogger<ItemController> logger,
|
|
33
|
+
IMapper mapper,
|
|
34
|
+
IItemService itemService)
|
|
35
|
+
{
|
|
36
|
+
_mapper = mapper;
|
|
37
|
+
_logger = logger;
|
|
38
|
+
_itemService = itemService;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// <summary>
|
|
42
|
+
/// Get items
|
|
43
|
+
/// </summary>
|
|
44
|
+
/// <param name="pagingParams"></param>
|
|
45
|
+
/// <returns></returns>
|
|
46
|
+
[HttpGet]
|
|
47
|
+
[ProducesResponseType(typeof(PagerData<ItemResponseDto>), StatusCodes.Status200OK)]
|
|
48
|
+
public async Task<IActionResult> GetItems([FromQuery] PagingParams pagingParams)
|
|
49
|
+
{
|
|
50
|
+
_logger.LogInformation($"Start getting items");
|
|
51
|
+
var stopwatch = Stopwatch.StartNew();
|
|
52
|
+
|
|
53
|
+
PagerData<Item> items = await _itemService.GetItemsAsync(pagingParams);
|
|
54
|
+
PagerData<ItemResponseDto> itemResponse = _mapper.Map<PagerData<ItemResponseDto>>(items);
|
|
55
|
+
|
|
56
|
+
// Add custom headers
|
|
57
|
+
Response.Headers.Append("X-WP-Total", items.TotalRecords.ToString());
|
|
58
|
+
|
|
59
|
+
stopwatch.Stop();
|
|
60
|
+
_logger.LogInformation($"Getting items done in {stopwatch.ElapsedMilliseconds}");
|
|
61
|
+
|
|
62
|
+
return Ok(itemResponse.Items);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
|
|
3
|
+
<PropertyGroup>
|
|
4
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
5
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
6
|
+
<Nullable>enable</Nullable>
|
|
7
|
+
</PropertyGroup>
|
|
8
|
+
|
|
9
|
+
<ItemGroup>
|
|
10
|
+
<Folder Include="Controllers\Admin\" />
|
|
11
|
+
</ItemGroup>
|
|
12
|
+
|
|
13
|
+
<ItemGroup>
|
|
14
|
+
<PackageReference Include="Asp.Versioning.Mvc" Version="8.1.1" />
|
|
15
|
+
<PackageReference Include="Asp.Versioning.Mvc.ApiExplorer" Version="8.1.1" />
|
|
16
|
+
<PackageReference Include="AutoMapper" Version="16.0.0" />
|
|
17
|
+
<PackageReference Include="Microsoft.AspNetCore.Authorization" Version="10.0.2" />
|
|
18
|
+
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.3.9" />
|
|
19
|
+
</ItemGroup>
|
|
20
|
+
|
|
21
|
+
<ItemGroup>
|
|
22
|
+
<ProjectReference Include="..\ItemModule.Core\ItemModule.Core.csproj" />
|
|
23
|
+
<ProjectReference Include="..\ItemModule.Infrastructure\ItemModule.Infrastructure.csproj" />
|
|
24
|
+
<ProjectReference Include="..\Shared.Core\Shared.Core.csproj" />
|
|
25
|
+
</ItemGroup>
|
|
26
|
+
|
|
27
|
+
</Project>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
using ItemModule.API.Controllers.Public;
|
|
2
|
+
using ItemModule.API.Mappers;
|
|
3
|
+
using ItemModule.Core;
|
|
4
|
+
using ItemModule.Infrastructure;
|
|
5
|
+
using Microsoft.Extensions.Configuration;
|
|
6
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
7
|
+
using Shared.Core.Interfaces.Modules;
|
|
8
|
+
using System.Reflection;
|
|
9
|
+
|
|
10
|
+
namespace ItemModule.API
|
|
11
|
+
{
|
|
12
|
+
public class ItemModule : IModule
|
|
13
|
+
{
|
|
14
|
+
public string Name => "Item";
|
|
15
|
+
public void Register(IServiceCollection services, IConfiguration config)
|
|
16
|
+
{
|
|
17
|
+
ItemCoreDependencyInjection.AddModule(services);
|
|
18
|
+
ItemInfraDependencyInjection.AddModule(services);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public Assembly ApiAssembly => typeof(ItemController).Assembly;
|
|
22
|
+
public Assembly MappingAssembly => typeof(DtoItemMappingProfile).Assembly;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
using AutoMapper;
|
|
2
|
+
using ItemModule.Core.Dtos.Admin;
|
|
3
|
+
using ItemModule.Core.Entities;
|
|
4
|
+
using Shared.Core.Shared.Models;
|
|
5
|
+
|
|
6
|
+
namespace ItemModule.API.Mappers
|
|
7
|
+
{
|
|
8
|
+
/// <summary>
|
|
9
|
+
/// DtoItemMappingProfile
|
|
10
|
+
/// </summary>
|
|
11
|
+
public class DtoItemMappingProfile : Profile
|
|
12
|
+
{
|
|
13
|
+
/// <summary>
|
|
14
|
+
/// Constructor
|
|
15
|
+
/// </summary>
|
|
16
|
+
public DtoItemMappingProfile()
|
|
17
|
+
{
|
|
18
|
+
CreateMap<Item, ItemRequestDto>().ReverseMap();
|
|
19
|
+
|
|
20
|
+
CreateMap<PagerData<Item>, PagerData<ItemResponseDto>>().ReverseMap();
|
|
21
|
+
|
|
22
|
+
CreateMap<Item, ItemResponseDto>()
|
|
23
|
+
.ReverseMap();
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
using ItemModule.Core.Interfaces.API;
|
|
2
|
+
using ItemModule.Core.Services;
|
|
3
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
4
|
+
using Shared.Core.Interfaces.API;
|
|
5
|
+
using Shared.Core.Services;
|
|
6
|
+
|
|
7
|
+
namespace ItemModule.Core
|
|
8
|
+
{
|
|
9
|
+
public static class ItemCoreDependencyInjection
|
|
10
|
+
{
|
|
11
|
+
public static IServiceCollection AddModule(
|
|
12
|
+
this IServiceCollection services)
|
|
13
|
+
{
|
|
14
|
+
services.AddScoped(typeof(IItemService<>), typeof(ItemService<>));
|
|
15
|
+
services.AddScoped<IItemService, ItemService>();
|
|
16
|
+
return services;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
|
|
3
|
+
<PropertyGroup>
|
|
4
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
5
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
6
|
+
<Nullable>enable</Nullable>
|
|
7
|
+
</PropertyGroup>
|
|
8
|
+
|
|
9
|
+
<ItemGroup>
|
|
10
|
+
<ProjectReference Include="..\Shared.Core\Shared.Core.csproj" />
|
|
11
|
+
</ItemGroup>
|
|
12
|
+
|
|
13
|
+
<ItemGroup>
|
|
14
|
+
<Folder Include="Dtos\Public\" />
|
|
15
|
+
<Folder Include="Enums\" />
|
|
16
|
+
</ItemGroup>
|
|
17
|
+
|
|
18
|
+
</Project>
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
using ItemModule.Core.Entities;
|
|
2
|
+
using ItemModule.Core.Interfaces.API;
|
|
3
|
+
using ItemModule.Core.Interfaces.SPI;
|
|
4
|
+
using Microsoft.Extensions.Logging;
|
|
5
|
+
using Shared.Core.Interfaces.SPI;
|
|
6
|
+
using Shared.Core.Services;
|
|
7
|
+
|
|
8
|
+
namespace ItemModule.Core.Services
|
|
9
|
+
{
|
|
10
|
+
public class ItemService : ItemService<Item>, IItemService
|
|
11
|
+
{
|
|
12
|
+
private readonly IItemInfra _userInfra;
|
|
13
|
+
public ItemService(ILogger<ItemService> logger,
|
|
14
|
+
IRepositoryFactory<Item> repositoryFactory,
|
|
15
|
+
IItemInfra userInfra) : base(logger, repositoryFactory)
|
|
16
|
+
{
|
|
17
|
+
_userInfra = userInfra;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
using ItemModule.Core.Entities;
|
|
2
|
+
using Microsoft.EntityFrameworkCore;
|
|
3
|
+
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
|
4
|
+
|
|
5
|
+
namespace ItemModule.Infrastructure.Database
|
|
6
|
+
{
|
|
7
|
+
internal class ItemConfiguration : IEntityTypeConfiguration<Item>
|
|
8
|
+
{
|
|
9
|
+
public void Configure(EntityTypeBuilder<Item> builder)
|
|
10
|
+
{
|
|
11
|
+
// Table
|
|
12
|
+
builder.ToTable("Items");
|
|
13
|
+
|
|
14
|
+
// Primary key
|
|
15
|
+
builder.HasKey(x => x.Id);
|
|
16
|
+
|
|
17
|
+
// BaseEntity (nếu có)
|
|
18
|
+
builder.Property(x => x.Id)
|
|
19
|
+
.IsRequired();
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
using ItemModule.Core.Entities;
|
|
2
|
+
using Microsoft.EntityFrameworkCore;
|
|
3
|
+
using Shared.Core.Enums;
|
|
4
|
+
using Shared.Core.Interfaces.SPI;
|
|
5
|
+
|
|
6
|
+
namespace ItemModule.Infrastructure.Database
|
|
7
|
+
{
|
|
8
|
+
public class Seeder : IModuleSeeder
|
|
9
|
+
{
|
|
10
|
+
public void Seed(ModelBuilder modelBuilder)
|
|
11
|
+
{
|
|
12
|
+
modelBuilder.Entity<Item>().HasData(
|
|
13
|
+
new Item
|
|
14
|
+
{
|
|
15
|
+
Id = Guid.Parse("11111111-1111-1111-1111-111111111111"),
|
|
16
|
+
Status = EntityStatus.Active,
|
|
17
|
+
}
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
using ItemModule.Core.Interfaces.SPI;
|
|
2
|
+
using ItemModule.Infrastructure.Database;
|
|
3
|
+
using ItemModule.Infrastructure.Services;
|
|
4
|
+
using Microsoft.Extensions.DependencyInjection;
|
|
5
|
+
using Shared.Core.Interfaces.SPI;
|
|
6
|
+
using Shared.Infrastructure.Services.MySQL;
|
|
7
|
+
|
|
8
|
+
namespace ItemModule.Infrastructure
|
|
9
|
+
{
|
|
10
|
+
public static class ItemInfraDependencyInjection
|
|
11
|
+
{
|
|
12
|
+
public static IServiceCollection AddModule(
|
|
13
|
+
this IServiceCollection services)
|
|
14
|
+
{
|
|
15
|
+
services.AddScoped<IModuleSeeder, Seeder>();
|
|
16
|
+
services.AddScoped<IItemInfra, MySQLItemInfra>();
|
|
17
|
+
services.AddScoped(typeof(IItemInfra<>), typeof(MySQLItemInfra<>));
|
|
18
|
+
return services;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<Project Sdk="Microsoft.NET.Sdk">
|
|
2
|
+
|
|
3
|
+
<PropertyGroup>
|
|
4
|
+
<TargetFramework>net10.0</TargetFramework>
|
|
5
|
+
<ImplicitUsings>enable</ImplicitUsings>
|
|
6
|
+
<Nullable>enable</Nullable>
|
|
7
|
+
</PropertyGroup>
|
|
8
|
+
|
|
9
|
+
<ItemGroup>
|
|
10
|
+
<ProjectReference Include="..\ItemModule.Core\ItemModule.Core.csproj" />
|
|
11
|
+
<ProjectReference Include="..\Shared.Infrastructure\Shared.Infrastructure.csproj" />
|
|
12
|
+
</ItemGroup>
|
|
13
|
+
|
|
14
|
+
</Project>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
using ItemModule.Core.Entities;
|
|
2
|
+
using ItemModule.Core.Interfaces.SPI;
|
|
3
|
+
using Microsoft.Extensions.Logging;
|
|
4
|
+
using Shared.Infrastructure.Database;
|
|
5
|
+
using Shared.Infrastructure.Services.MySQL;
|
|
6
|
+
|
|
7
|
+
namespace ItemModule.Infrastructure.Services
|
|
8
|
+
{
|
|
9
|
+
public class MySQLItemInfra : MySQLItemInfra<Item>, IItemInfra
|
|
10
|
+
{
|
|
11
|
+
public MySQLItemInfra(MyDbContext dbContext, ILogger<MySQLItemInfra> logger)
|
|
12
|
+
: base(dbContext, logger)
|
|
13
|
+
{
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
package/bin/create-module.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
1
3
|
const fs = require('fs');
|
|
2
4
|
const path = require('path');
|
|
3
5
|
|
|
@@ -8,59 +10,70 @@ if (!newModuleName) {
|
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
const sourceModuleName = "ItemModule";
|
|
11
|
-
const templatePath = path.join(__dirname, "..", "BlueprintTemplate");
|
|
12
|
-
const destinationRoot = process.cwd(); // project root
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// 🔥 NEW: Modules folder (not BlueprintTemplate)
|
|
15
|
+
const modulesTemplateRoot = path.join(__dirname, "..", "Modules");
|
|
16
|
+
const sourceModulePath = path.join(modulesTemplateRoot, sourceModuleName);
|
|
17
|
+
|
|
18
|
+
// Project root where new module will be created
|
|
19
|
+
const destinationRoot = process.cwd();
|
|
20
|
+
const destinationModulePath = path.join(destinationRoot, newModuleName);
|
|
21
|
+
|
|
22
|
+
if (!fs.existsSync(sourceModulePath)) {
|
|
23
|
+
console.error(`❌ Source module not found: ${sourceModulePath}`);
|
|
16
24
|
process.exit(1);
|
|
17
25
|
}
|
|
18
26
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
.filter(d => d.isDirectory() && d.name.startsWith(sourceModuleName));
|
|
22
|
-
|
|
23
|
-
if (sourceFolders.length === 0) {
|
|
24
|
-
console.error(`❌ No ItemModule templates found in: ${templatePath}`);
|
|
27
|
+
if (fs.existsSync(destinationModulePath)) {
|
|
28
|
+
console.error(`❌ Destination module already exists: ${destinationModulePath}`);
|
|
25
29
|
process.exit(1);
|
|
26
30
|
}
|
|
27
31
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
new RegExp(sourceModuleName, 'g'),
|
|
32
|
-
newModuleName
|
|
33
|
-
);
|
|
34
|
-
const destPath = path.join(destinationRoot, destName);
|
|
35
|
-
|
|
36
|
-
if (fs.existsSync(destPath)) {
|
|
37
|
-
console.error(`❌ Destination already exists: ${destPath}`);
|
|
38
|
-
process.exit(1);
|
|
39
|
-
}
|
|
32
|
+
console.log(`📦 Creating module: ${newModuleName}`);
|
|
33
|
+
console.log(`📁 From template: ${sourceModulePath}`);
|
|
34
|
+
console.log(`📁 To: ${destinationModulePath}`);
|
|
40
35
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
copyAndRenameFiles(
|
|
37
|
+
sourceModulePath,
|
|
38
|
+
destinationModulePath,
|
|
39
|
+
sourceModuleName,
|
|
40
|
+
newModuleName
|
|
41
|
+
);
|
|
44
42
|
|
|
45
43
|
console.log(`🎉 Module "${newModuleName}" created successfully!`);
|
|
46
44
|
|
|
47
45
|
// ===== CORE LOGIC =====
|
|
48
46
|
|
|
49
47
|
function copyAndRenameFiles(src, dest, oldName, newName) {
|
|
50
|
-
|
|
48
|
+
const stat = fs.lstatSync(src);
|
|
49
|
+
|
|
50
|
+
if (stat.isDirectory()) {
|
|
51
51
|
fs.mkdirSync(dest, { recursive: true });
|
|
52
|
+
|
|
52
53
|
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
53
54
|
|
|
54
|
-
for (
|
|
55
|
+
for (const entry of entries) {
|
|
55
56
|
const srcPath = path.join(src, entry.name);
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
// 🔁 Rename folder/file if contains old module name
|
|
59
|
+
const renamed = entry.name.replace(
|
|
60
|
+
new RegExp(oldName, 'g'),
|
|
61
|
+
newName
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
const destPath = path.join(dest, renamed);
|
|
58
65
|
|
|
59
66
|
copyAndRenameFiles(srcPath, destPath, oldName, newName);
|
|
60
67
|
}
|
|
61
68
|
} else {
|
|
62
69
|
let content = fs.readFileSync(src, 'utf8');
|
|
63
|
-
|
|
70
|
+
|
|
71
|
+
// 🔁 Replace namespace + content
|
|
72
|
+
content = content.replace(
|
|
73
|
+
new RegExp(oldName, 'g'),
|
|
74
|
+
newName
|
|
75
|
+
);
|
|
76
|
+
|
|
64
77
|
fs.writeFileSync(dest, content, 'utf8');
|
|
65
78
|
}
|
|
66
79
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "netcore-blueprint",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.18",
|
|
4
4
|
"description": "A custom project blueprint",
|
|
5
5
|
"main": "create.js",
|
|
6
6
|
"bin": {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"author": "",
|
|
18
18
|
"license": "ISC",
|
|
19
19
|
"files": [
|
|
20
|
-
"
|
|
20
|
+
"Modules/**",
|
|
21
21
|
"BlueprintTemplate/**"
|
|
22
22
|
]
|
|
23
23
|
}
|