@atlashub/smartstack-cli 4.4.0 → 4.6.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "4.4.0",
3
+ "version": "4.6.0",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -17,8 +17,8 @@ public static class DependencyInjection
17
17
  this IServiceCollection services)
18
18
  {
19
19
  // TODO: Register your application services here
20
- // Example:
21
- // services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(typeof(DependencyInjection).Assembly));
20
+ // NOTE: MediatR is already registered by AddSmartStack() — do NOT register it again here.
21
+ // Only add client-specific services (e.g., custom validators, domain services).
22
22
 
23
23
  return services;
24
24
  }
@@ -1,47 +1,101 @@
1
+ using Serilog;
2
+ using Serilog.Events;
1
3
  using Microsoft.EntityFrameworkCore;
2
4
  using SmartStack.Api.Extensions;
3
5
  using {{ProjectName}}.Infrastructure;
4
6
  using {{ProjectName}}.Infrastructure.Persistence;
5
7
  using {{ProjectName}}.Application;
6
8
 
7
- var builder = WebApplication.CreateBuilder(args);
9
+ // Bootstrap logger for startup errors
10
+ Log.Logger = new LoggerConfiguration()
11
+ .MinimumLevel.Override("Microsoft", LogEventLevel.Information)
12
+ .Enrich.FromLogContext()
13
+ .WriteTo.Console()
14
+ .CreateBootstrapLogger();
8
15
 
9
- // ===================================================================
10
- // 1. Add SmartStack Core services (from NuGet package)
11
- // ===================================================================
12
- builder.Services.AddSmartStack(builder.Configuration, options =>
16
+ try
13
17
  {
14
- options.EnableDevSeeding = builder.Environment.IsDevelopment();
15
- options.EnableSwagger = builder.Environment.IsDevelopment();
16
- });
17
-
18
- // ===================================================================
19
- // 2. Add client-specific services (Dual-DbContext pattern)
20
- // ===================================================================
21
- builder.Services.Add{{ProjectName}}Infrastructure(builder.Configuration);
22
- builder.Services.Add{{ProjectName}}Application();
23
-
24
- var app = builder.Build();
25
-
26
- // ===================================================================
27
- // 3. Initialize SmartStack + apply migrations (in correct order!)
28
- // ===================================================================
29
- // This initializes SmartStack and applies Core migrations automatically
30
- await app.InitializeSmartStackAsync();
31
-
32
- // Apply Extensions migrations AFTER Core migrations
33
- // Your client-specific tables may have FK references to Core tables
34
- if (app.Environment.IsDevelopment())
35
- {
36
- using var scope = app.Services.CreateScope();
37
- var extDb = scope.ServiceProvider.GetRequiredService<ExtensionsDbContext>();
38
- await extDb.Database.MigrateAsync();
39
- }
18
+ Log.Information("Starting {{ProjectName}} API");
19
+
20
+ var builder = WebApplication.CreateBuilder(args);
21
+
22
+ // Configure Kestrel to use HTTP/1.1 on all configured endpoints
23
+ builder.WebHost.ConfigureKestrel((context, options) =>
24
+ {
25
+ options.ConfigureEndpointDefaults(listenOptions =>
26
+ {
27
+ listenOptions.Protocols = Microsoft.AspNetCore.Server.Kestrel.Core.HttpProtocols.Http1;
28
+ });
29
+ });
30
+
31
+ // Load appsettings.Local.json if it exists (for local development overrides)
32
+ builder.Configuration.AddJsonFile("appsettings.Local.json", optional: true, reloadOnChange: true);
33
+
34
+ // Serilog configuration from appsettings
35
+ builder.Host.UseSmartStackSerilog();
36
+
37
+ // Application Insights SDK (must be added before Serilog runs)
38
+ var aiConnectionString = builder.Configuration["Logging:Sinks:ApplicationInsights:ConnectionString"];
39
+ var aiEnabled = builder.Configuration.GetValue<bool>("Logging:Sinks:ApplicationInsights:Enabled");
40
+ if (!string.IsNullOrEmpty(aiConnectionString) && aiEnabled)
41
+ {
42
+ builder.Services.AddApplicationInsightsTelemetry(options =>
43
+ {
44
+ options.ConnectionString = aiConnectionString;
45
+ });
46
+ }
47
+
48
+ // ===================================================================
49
+ // 1. Add SmartStack Core services (from NuGet package)
50
+ // ===================================================================
51
+ builder.Services.AddSmartStack(builder.Configuration, options =>
52
+ {
53
+ options.EnableDevSeeding = builder.Environment.IsDevelopment();
54
+ });
55
+
56
+ // ===================================================================
57
+ // 2. Add client-specific services (Dual-DbContext pattern)
58
+ // ===================================================================
59
+ builder.Services.Add{{ProjectName}}Infrastructure(builder.Configuration);
60
+ builder.Services.Add{{ProjectName}}Application();
61
+
62
+ var app = builder.Build();
40
63
 
41
- // ===================================================================
42
- // 4. SmartStack middleware & endpoints
43
- // ===================================================================
44
- app.UseSmartStack();
45
- app.MapSmartStack();
64
+ // ===================================================================
65
+ // 3. Initialize SmartStack + apply migrations (in correct order!)
66
+ // ===================================================================
67
+ // This initializes SmartStack and applies Core migrations automatically
68
+ await app.InitializeSmartStackAsync();
46
69
 
47
- app.Run();
70
+ // Apply Extensions migrations AFTER Core migrations
71
+ // Your client-specific tables may have FK references to Core tables
72
+ if (app.Environment.IsDevelopment())
73
+ {
74
+ using var scope = app.Services.CreateScope();
75
+ var extDb = scope.ServiceProvider.GetRequiredService<ExtensionsDbContext>();
76
+ await extDb.Database.MigrateAsync();
77
+ }
78
+
79
+ // ===================================================================
80
+ // 4. SmartStack middleware & endpoints
81
+ // ===================================================================
82
+ // Swagger UI (development only)
83
+ app.UseSmartStackSwagger();
84
+
85
+ // SmartStack middleware pipeline
86
+ app.UseSmartStack();
87
+
88
+ // Map controllers and SignalR hubs
89
+ app.MapSmartStack();
90
+
91
+ Log.Information("{{ProjectName}} API started successfully");
92
+ app.Run();
93
+ }
94
+ catch (Exception ex)
95
+ {
96
+ Log.Fatal(ex, "Application terminated unexpectedly");
97
+ }
98
+ finally
99
+ {
100
+ Log.CloseAndFlush();
101
+ }
@@ -6,17 +6,15 @@
6
6
  "AutoMigrate": true,
7
7
  "FailOnMigrationError": true,
8
8
  "EnableDevSeeding": false,
9
- "UseAzureStorage": false,
10
- "UseEntraId": false,
11
- "EnableSwagger": true,
12
9
  "CorsOrigins": [
13
- "http://localhost:3000",
14
10
  "http://localhost:5173",
15
11
  "http://localhost:5174",
16
- "http://localhost:5175"
12
+ "http://localhost:5175",
13
+ "http://localhost:6173"
17
14
  ]
18
15
  },
19
16
  "Jwt": {
17
+ "RsaPrivateKeyPem": "",
20
18
  "Secret": "{{JwtSecret}}",
21
19
  "Issuer": "{{ProjectName}}",
22
20
  "Audience": "{{ProjectName}}",
@@ -27,14 +25,16 @@
27
25
  "Microsoft": {
28
26
  "ClientId": "",
29
27
  "ClientSecret": "",
28
+ "SecretExpiresAt": "",
30
29
  "CallbackPath": "/api/auth/microsoft/callback"
31
30
  },
32
31
  "Google": {
33
32
  "ClientId": "",
34
33
  "ClientSecret": "",
34
+ "SecretExpiresAt": "",
35
35
  "CallbackPath": "/api/auth/google/callback"
36
36
  },
37
- "FrontendUrl": "http://localhost:5173"
37
+ "FrontendUrl": "http://localhost:6173"
38
38
  },
39
39
  "Session": {
40
40
  "IdleTimeoutMinutes": 20,
@@ -43,7 +43,7 @@
43
43
  "EnableValidation": true,
44
44
  "RefreshTokenExpirationDays": 7,
45
45
  "CleanupBatchSize": 100,
46
- "MaxConcurrentSessions": 3,
46
+ "MaxConcurrentSessions": 1,
47
47
  "CleanupIntervalMinutes": 5
48
48
  },
49
49
  "Serilog": {
@@ -82,6 +82,10 @@
82
82
  }
83
83
  }
84
84
  },
85
+ "Redis": {
86
+ "Enabled": false,
87
+ "ConnectionString": "localhost:6379"
88
+ },
85
89
  "AzureStorage": {
86
90
  "UseAzure": false,
87
91
  "Normal": {
@@ -155,6 +159,11 @@
155
159
  "UseDeltaSync": true,
156
160
  "DefaultConflictResolution": "ManualReview",
157
161
  "AutoCreateReferences": true,
162
+ "BackgroundSyncEnabled": false,
163
+ "BackgroundSyncIntervalMinutes": 60,
164
+ "MaxGraphQueryPageSize": 999
165
+ },
166
+ "Glpi": {
158
167
  "BackgroundSyncEnabled": false,
159
168
  "BackgroundSyncIntervalMinutes": 60
160
169
  },
@@ -166,5 +175,23 @@
166
175
  "SystemTenantName": "Default Workspace",
167
176
  "AutoAssignUsersToSystemTenant": true
168
177
  },
178
+ "LicenseServer": {
179
+ "BaseUrl": "https://license.atlashub.ch/",
180
+ "ApiKey": "",
181
+ "Enabled": true,
182
+ "HeartbeatIntervalHours": 168,
183
+ "StartupDelaySeconds": 30,
184
+ "TimeoutSeconds": 30,
185
+ "RetryCount": 3,
186
+ "RetryDelaySeconds": 5
187
+ },
188
+ "Security": {
189
+ "LockoutWindowMinutes": 15,
190
+ "MaxFailedAttempts": 5
191
+ },
192
+ "Localization": {
193
+ "DefaultLanguage": "fr",
194
+ "FallbackLanguage": "fr"
195
+ },
169
196
  "AllowedHosts": "*"
170
197
  }
@@ -542,15 +542,17 @@ public record CustomerResponseDto(
542
542
 
543
543
  ```tsx
544
544
  // Composite columns from response DTO (already resolved by backend)
545
- <SmartTable
545
+ <DataTable
546
546
  columns={[
547
- { key: 'code', label: t('module:columns.code', 'Code') },
548
- { key: 'displayFirstName', label: t('module:columns.firstName', 'First Name') },
549
- { key: 'displayLastName', label: t('module:columns.lastName', 'Last Name') },
550
- { key: 'displayEmail', label: t('module:columns.email', 'Email') },
547
+ { key: 'code', label: t('module:columns.code', 'Code'), sortable: true },
548
+ { key: 'displayFirstName', label: t('module:columns.firstName', 'First Name'), sortable: true },
549
+ { key: 'displayLastName', label: t('module:columns.lastName', 'Last Name'), sortable: true },
550
+ { key: 'displayEmail', label: t('module:columns.email', 'Email'), sortable: true },
551
551
  { key: 'status', label: t('module:columns.status', 'Status') },
552
552
  ]}
553
553
  data={items}
554
+ searchable
555
+ pagination={{ pageSize: 10 }}
554
556
  />
555
557
  ```
556
558