@atlashub/smartstack-cli 1.13.2 → 1.14.1

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.
Files changed (214) hide show
  1. package/.documentation/agents.html +1 -1
  2. package/.documentation/apex.html +1 -1
  3. package/.documentation/business-analyse.html +1 -1
  4. package/.documentation/cli-commands.html +3 -3
  5. package/.documentation/commands.html +1 -1
  6. package/.documentation/efcore.html +1 -1
  7. package/.documentation/gitflow.html +231 -236
  8. package/.documentation/hooks.html +1 -1
  9. package/.documentation/index.html +1 -1
  10. package/.documentation/init.html +3 -3
  11. package/.documentation/installation.html +1075 -351
  12. package/.documentation/ralph-loop.html +1 -1
  13. package/.documentation/test-web.html +1 -1
  14. package/README.md +88 -20
  15. package/config/default-config.json +10 -1
  16. package/dist/index.js +276 -85
  17. package/dist/index.js.map +1 -1
  18. package/package.json +1 -1
  19. package/templates/agents/code-reviewer.md +163 -0
  20. package/templates/agents/efcore/db-deploy.md +25 -7
  21. package/templates/agents/efcore/db-reset.md +31 -10
  22. package/templates/agents/efcore/db-status.md +22 -5
  23. package/templates/agents/efcore/migration.md +70 -20
  24. package/templates/agents/gitflow/cleanup.md +8 -1
  25. package/templates/agents/gitflow/commit.md +7 -5
  26. package/templates/agents/gitflow/finish.md +6 -4
  27. package/templates/agents/gitflow/pr.md +8 -1
  28. package/templates/agents/gitflow/start.md +1 -1
  29. package/templates/commands/check-version.md +267 -0
  30. package/templates/commands/efcore/_shared.md +31 -2
  31. package/templates/commands/efcore/db-reset.md +18 -6
  32. package/templates/commands/efcore/migration.md +1 -1
  33. package/templates/commands/efcore/rebase-snapshot.md +1 -1
  34. package/templates/commands/efcore/squash.md +1 -0
  35. package/templates/commands/refactor.md +164 -0
  36. package/templates/project/DependencyInjection.Application.cs.template +25 -0
  37. package/templates/project/DependencyInjection.Infrastructure.cs.template +61 -0
  38. package/templates/project/DesignTimeExtensionsDbContextFactory.cs.template +70 -0
  39. package/templates/project/ExampleEntity.cs.template +116 -0
  40. package/templates/project/ExampleEntityConfiguration.cs.template +64 -0
  41. package/templates/project/ExampleService.cs.template +146 -0
  42. package/templates/project/ExtensionsDbContext.cs.template +41 -0
  43. package/templates/project/IExtensionsDbContext.cs.template +22 -0
  44. package/templates/project/Program.cs.template +47 -0
  45. package/templates/project/README.md +79 -0
  46. package/templates/ralph/README.md +10 -8
  47. package/templates/ralph/ralph.config.yaml +2 -2
  48. package/templates/skills/_shared.md +44 -44
  49. package/templates/skills/ai-prompt/SKILL.md +55 -55
  50. package/templates/skills/apex/SKILL.md +235 -0
  51. package/templates/skills/apex/steps/step-00-init.md +203 -0
  52. package/templates/skills/apex/steps/step-01-analyze.md +210 -0
  53. package/templates/skills/apex/steps/step-02-plan.md +217 -0
  54. package/templates/skills/apex/steps/step-03-execute.md +178 -0
  55. package/templates/skills/apex/steps/step-04-validate.md +217 -0
  56. package/templates/skills/apex/steps/step-05-examine.md +207 -0
  57. package/templates/skills/apex/steps/step-06-resolve.md +181 -0
  58. package/templates/skills/apex/steps/step-07-tests.md +206 -0
  59. package/templates/skills/apex/steps/step-08-run-tests.md +207 -0
  60. package/templates/skills/apex/templates/00-context.md +46 -0
  61. package/templates/skills/apex/templates/01-analyze.md +63 -0
  62. package/templates/skills/apex/templates/02-plan.md +63 -0
  63. package/templates/skills/apex/templates/03-execute.md +34 -0
  64. package/templates/skills/apex/templates/04-validate.md +61 -0
  65. package/templates/skills/apex/templates/05-examine.md +58 -0
  66. package/templates/skills/apex/templates/06-resolve.md +39 -0
  67. package/templates/skills/apex/templates/07-tests.md +56 -0
  68. package/templates/skills/apex/templates/08-run-tests.md +41 -0
  69. package/templates/skills/apex/templates/README.md +69 -0
  70. package/templates/skills/application/SKILL.md +50 -50
  71. package/templates/skills/application/templates-backend.md +25 -25
  72. package/templates/skills/application/templates-frontend.md +43 -43
  73. package/templates/skills/application/templates-i18n.md +29 -29
  74. package/templates/skills/application/templates-seed.md +77 -77
  75. package/templates/skills/business-analyse/SKILL.md +223 -0
  76. package/templates/skills/business-analyse/_shared.md +258 -0
  77. package/templates/skills/business-analyse/questionnaire/01-context.md +33 -0
  78. package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +35 -0
  79. package/templates/skills/business-analyse/questionnaire/03-scope.md +35 -0
  80. package/templates/skills/business-analyse/questionnaire/04-data.md +36 -0
  81. package/templates/skills/business-analyse/questionnaire/05-integrations.md +36 -0
  82. package/templates/skills/business-analyse/questionnaire/06-security.md +40 -0
  83. package/templates/skills/business-analyse/questionnaire/07-ui.md +36 -0
  84. package/templates/skills/business-analyse/questionnaire/08-performance.md +35 -0
  85. package/templates/skills/business-analyse/questionnaire/09-constraints.md +35 -0
  86. package/templates/skills/business-analyse/questionnaire/10-documentation.md +35 -0
  87. package/templates/skills/business-analyse/questionnaire.md +177 -177
  88. package/templates/skills/business-analyse/react/components.md +340 -0
  89. package/templates/skills/business-analyse/react/i18n-template.md +245 -0
  90. package/templates/skills/business-analyse/react/schema.md +151 -0
  91. package/templates/skills/business-analyse/steps/step-00-init.md +293 -0
  92. package/templates/skills/business-analyse/steps/step-01-discover.md +267 -0
  93. package/templates/skills/business-analyse/steps/step-02-analyse.md +243 -0
  94. package/templates/skills/business-analyse/steps/step-03-specify.md +317 -0
  95. package/templates/skills/business-analyse/steps/step-04-validate.md +239 -0
  96. package/templates/skills/business-analyse/steps/step-05-handoff.md +336 -0
  97. package/templates/skills/business-analyse/steps/step-06-doc-html.md +261 -0
  98. package/templates/skills/business-analyse/templates/00-context.md +105 -0
  99. package/templates/skills/business-analyse/templates/frd-brd.md +97 -0
  100. package/templates/skills/business-analyse/templates/frd-discovery.md +78 -0
  101. package/templates/skills/business-analyse/templates/frd-handoff.md +118 -0
  102. package/templates/skills/business-analyse/templates/frd-spec.md +168 -0
  103. package/templates/skills/business-analyse/templates-frd.md +217 -217
  104. package/templates/skills/business-analyse/templates-react.md +26 -26
  105. package/templates/skills/controller/SKILL.md +141 -92
  106. package/templates/skills/controller/postman-templates.md +15 -15
  107. package/templates/skills/controller/steps/step-00-init.md +191 -0
  108. package/templates/skills/controller/steps/step-01-analyze.md +146 -0
  109. package/templates/skills/controller/steps/step-02-plan.md +176 -0
  110. package/templates/skills/controller/steps/step-03-generate.md +219 -0
  111. package/templates/skills/controller/steps/step-04-perms.md +219 -0
  112. package/templates/skills/controller/steps/step-05-validate.md +107 -0
  113. package/templates/skills/controller/templates.md +77 -77
  114. package/templates/skills/documentation/SKILL.md +79 -79
  115. package/templates/skills/feature-full/SKILL.md +38 -38
  116. package/templates/skills/gitflow/SKILL.md +277 -0
  117. package/templates/{commands → skills}/gitflow/_shared.md +20 -20
  118. package/templates/skills/gitflow/phases/abort.md +173 -0
  119. package/templates/skills/gitflow/phases/cleanup.md +226 -0
  120. package/templates/skills/gitflow/phases/status.md +178 -0
  121. package/templates/skills/gitflow/steps/step-commit.md +255 -0
  122. package/templates/skills/gitflow/steps/step-finish.md +255 -0
  123. package/templates/skills/gitflow/steps/step-init.md +209 -0
  124. package/templates/skills/gitflow/steps/step-merge.md +225 -0
  125. package/templates/skills/gitflow/steps/step-plan.md +208 -0
  126. package/templates/skills/gitflow/steps/step-pr.md +235 -0
  127. package/templates/skills/gitflow/steps/step-start.md +334 -0
  128. package/templates/skills/gitflow/steps/step-sync.md +200 -0
  129. package/templates/skills/gitflow/templates/config.json +53 -0
  130. package/templates/skills/notification/SKILL.md +51 -51
  131. package/templates/skills/ralph-loop/SKILL.md +228 -0
  132. package/templates/skills/ralph-loop/steps/step-00-init.md +201 -0
  133. package/templates/skills/ralph-loop/steps/step-01-task.md +169 -0
  134. package/templates/skills/ralph-loop/steps/step-02-execute.md +173 -0
  135. package/templates/skills/ralph-loop/steps/step-03-commit.md +170 -0
  136. package/templates/skills/ralph-loop/steps/step-04-check.md +162 -0
  137. package/templates/skills/ralph-loop/steps/step-05-report.md +181 -0
  138. package/templates/skills/review-code/SKILL.md +219 -0
  139. package/templates/skills/review-code/references/clean-code-principles.md +140 -0
  140. package/templates/skills/review-code/references/code-quality-metrics.md +174 -0
  141. package/templates/skills/review-code/references/feedback-patterns.md +149 -0
  142. package/templates/skills/review-code/references/security-checklist.md +127 -0
  143. package/templates/skills/ui-components/SKILL.md +54 -54
  144. package/templates/skills/workflow/SKILL.md +46 -46
  145. package/templates/commands/ai-prompt.md +0 -315
  146. package/templates/commands/apex/1-analyze.md +0 -100
  147. package/templates/commands/apex/2-plan.md +0 -145
  148. package/templates/commands/apex/3-execute.md +0 -171
  149. package/templates/commands/apex/4-examine.md +0 -116
  150. package/templates/commands/apex/5-tasks.md +0 -209
  151. package/templates/commands/apex.md +0 -76
  152. package/templates/commands/application/create.md +0 -362
  153. package/templates/commands/application/templates-backend.md +0 -463
  154. package/templates/commands/application/templates-frontend.md +0 -517
  155. package/templates/commands/application/templates-i18n.md +0 -478
  156. package/templates/commands/application/templates-seed.md +0 -362
  157. package/templates/commands/application.md +0 -303
  158. package/templates/commands/business-analyse/0-orchestrate.md +0 -156
  159. package/templates/commands/business-analyse/1-init.md +0 -99
  160. package/templates/commands/business-analyse/2-discover.md +0 -143
  161. package/templates/commands/business-analyse/3-analyse.md +0 -106
  162. package/templates/commands/business-analyse/4-specify.md +0 -133
  163. package/templates/commands/business-analyse/5-validate.md +0 -132
  164. package/templates/commands/business-analyse/6-handoff.md +0 -157
  165. package/templates/commands/business-analyse/7-doc-html.md +0 -103
  166. package/templates/commands/business-analyse/_shared.md +0 -176
  167. package/templates/commands/business-analyse/bug.md +0 -118
  168. package/templates/commands/business-analyse/change-request.md +0 -144
  169. package/templates/commands/business-analyse/hotfix.md +0 -116
  170. package/templates/commands/business-analyse.md +0 -121
  171. package/templates/commands/controller/create.md +0 -216
  172. package/templates/commands/controller/postman-templates.md +0 -528
  173. package/templates/commands/controller/templates.md +0 -600
  174. package/templates/commands/controller.md +0 -337
  175. package/templates/commands/create/agent.md +0 -138
  176. package/templates/commands/create/command.md +0 -166
  177. package/templates/commands/create/hook.md +0 -234
  178. package/templates/commands/create/plugin.md +0 -329
  179. package/templates/commands/create/project.md +0 -508
  180. package/templates/commands/create/skill.md +0 -199
  181. package/templates/commands/create.md +0 -220
  182. package/templates/commands/documentation/module.md +0 -202
  183. package/templates/commands/documentation/templates.md +0 -432
  184. package/templates/commands/documentation.md +0 -190
  185. package/templates/commands/epct.md +0 -69
  186. package/templates/commands/explain.md +0 -186
  187. package/templates/commands/feature-full.md +0 -267
  188. package/templates/commands/gitflow/1-init.md +0 -188
  189. package/templates/commands/gitflow/10-start.md +0 -190
  190. package/templates/commands/gitflow/11-finish.md +0 -382
  191. package/templates/commands/gitflow/12-cleanup.md +0 -103
  192. package/templates/commands/gitflow/13-sync.md +0 -216
  193. package/templates/commands/gitflow/14-rebase.md +0 -251
  194. package/templates/commands/gitflow/2-status.md +0 -122
  195. package/templates/commands/gitflow/3-commit.md +0 -209
  196. package/templates/commands/gitflow/4-plan.md +0 -174
  197. package/templates/commands/gitflow/5-exec.md +0 -202
  198. package/templates/commands/gitflow/6-abort.md +0 -121
  199. package/templates/commands/gitflow/7-pull-request.md +0 -176
  200. package/templates/commands/gitflow/8-review.md +0 -113
  201. package/templates/commands/gitflow/9-merge.md +0 -157
  202. package/templates/commands/gitflow.md +0 -128
  203. package/templates/commands/implement.md +0 -663
  204. package/templates/commands/init.md +0 -567
  205. package/templates/commands/mcp-integration.md +0 -330
  206. package/templates/commands/notification.md +0 -129
  207. package/templates/commands/oneshot.md +0 -57
  208. package/templates/commands/quickstart.md +0 -154
  209. package/templates/commands/ralph-loop/cancel-ralph.md +0 -18
  210. package/templates/commands/ralph-loop/help.md +0 -126
  211. package/templates/commands/ralph-loop/ralph-loop.md +0 -120
  212. package/templates/commands/review.md +0 -106
  213. package/templates/commands/workflow.md +0 -193
  214. package/templates/gitflow/config.json +0 -138
@@ -0,0 +1,70 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+ using Microsoft.EntityFrameworkCore.Design;
3
+ using Microsoft.Extensions.Configuration;
4
+ using SmartStack.Infrastructure.Persistence.Configurations;
5
+
6
+ namespace {{ProjectName}}.Infrastructure.Persistence;
7
+
8
+ /// <summary>
9
+ /// Factory for creating ExtensionsDbContext at design time (for EF Core CLI tools).
10
+ ///
11
+ /// This enables running migrations from the command line:
12
+ /// <code>
13
+ /// dotnet ef migrations add MyMigration --context ExtensionsDbContext
14
+ /// dotnet ef database update --context ExtensionsDbContext
15
+ /// dotnet ef migrations list --context ExtensionsDbContext
16
+ /// dotnet ef migrations script --context ExtensionsDbContext -o deploy.sql
17
+ /// </code>
18
+ ///
19
+ /// IMPORTANT: Migrations are stored in the 'extensions' schema, separate from
20
+ /// SmartStack Core migrations in the 'core' schema.
21
+ /// </summary>
22
+ public class DesignTimeExtensionsDbContextFactory : IDesignTimeDbContextFactory<ExtensionsDbContext>
23
+ {
24
+ public ExtensionsDbContext CreateDbContext(string[] args)
25
+ {
26
+ // Try to find appsettings.json in various locations
27
+ var basePath = Directory.GetCurrentDirectory();
28
+
29
+ // Look for appsettings.json in common locations
30
+ var configPaths = new[]
31
+ {
32
+ basePath,
33
+ Path.Combine(basePath, "..", "{{ProjectName}}.Api"),
34
+ Path.Combine(basePath, "..", "..", "src", "{{ProjectName}}.Api"),
35
+ };
36
+
37
+ IConfigurationRoot? configuration = null;
38
+
39
+ foreach (var path in configPaths)
40
+ {
41
+ var configPath = Path.Combine(path, "appsettings.json");
42
+ if (File.Exists(configPath))
43
+ {
44
+ configuration = new ConfigurationBuilder()
45
+ .SetBasePath(path)
46
+ .AddJsonFile("appsettings.json", optional: false)
47
+ .AddJsonFile("appsettings.Development.json", optional: true)
48
+ .AddJsonFile("appsettings.Local.json", optional: true)
49
+ .Build();
50
+ break;
51
+ }
52
+ }
53
+
54
+ // Fallback: use a default connection string for design-time operations
55
+ var connectionString = configuration?.GetConnectionString("DefaultConnection")
56
+ ?? "Server=(localdb)\\mssqllocaldb;Database={{ProjectName}}_DesignTime;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True";
57
+
58
+ var optionsBuilder = new DbContextOptionsBuilder<ExtensionsDbContext>();
59
+ optionsBuilder.UseSqlServer(connectionString, b =>
60
+ {
61
+ b.MigrationsAssembly(typeof(ExtensionsDbContext).Assembly.FullName);
62
+
63
+ // IMPORTANT: Store migrations history in 'extensions' schema
64
+ // This keeps client migrations separate from Core migrations
65
+ b.MigrationsHistoryTable("__EFMigrationsHistory", SchemaConstants.Extensions);
66
+ });
67
+
68
+ return new ExtensionsDbContext(optionsBuilder.Options);
69
+ }
70
+ }
@@ -0,0 +1,116 @@
1
+ using SmartStack.Domain.Common;
2
+
3
+ namespace {{ProjectName}}.Domain.Entities;
4
+
5
+ /// <summary>
6
+ /// Example entity demonstrating FK reference to Core entities.
7
+ ///
8
+ /// IMPORTANT: Notice that we store only the UserId (GUID), NOT a navigation property.
9
+ /// This is because ExtensionsDbContext doesn't know about Core entities.
10
+ /// Use ICoreDataService to fetch the User data when needed.
11
+ /// </summary>
12
+ public class Order : BaseAuditableEntity
13
+ {
14
+ /// <summary>
15
+ /// Order number (auto-generated or custom format).
16
+ /// </summary>
17
+ public string OrderNumber { get; private set; } = null!;
18
+
19
+ /// <summary>
20
+ /// Foreign key to the User who created this order.
21
+ ///
22
+ /// IMPORTANT: This is a GUID reference only, NOT a navigation property!
23
+ /// Use ICoreDataService.GetUserByIdAsync() to fetch user details.
24
+ /// </summary>
25
+ public Guid CustomerId { get; private set; }
26
+
27
+ /// <summary>
28
+ /// Order status.
29
+ /// </summary>
30
+ public OrderStatus Status { get; private set; }
31
+
32
+ /// <summary>
33
+ /// Total amount.
34
+ /// </summary>
35
+ public decimal TotalAmount { get; private set; }
36
+
37
+ /// <summary>
38
+ /// Order date.
39
+ /// </summary>
40
+ public DateTime OrderDate { get; private set; }
41
+
42
+ /// <summary>
43
+ /// Optional notes.
44
+ /// </summary>
45
+ public string? Notes { get; private set; }
46
+
47
+ // Private constructor for EF Core
48
+ private Order() { }
49
+
50
+ /// <summary>
51
+ /// Creates a new order.
52
+ /// </summary>
53
+ /// <param name="orderNumber">Order number</param>
54
+ /// <param name="customerId">ID of the user placing the order (from Core)</param>
55
+ /// <param name="totalAmount">Total amount</param>
56
+ public static Order Create(string orderNumber, Guid customerId, decimal totalAmount)
57
+ {
58
+ return new Order
59
+ {
60
+ OrderNumber = orderNumber,
61
+ CustomerId = customerId,
62
+ Status = OrderStatus.Pending,
63
+ TotalAmount = totalAmount,
64
+ OrderDate = DateTime.UtcNow
65
+ };
66
+ }
67
+
68
+ public void Confirm()
69
+ {
70
+ if (Status != OrderStatus.Pending)
71
+ throw new InvalidOperationException("Only pending orders can be confirmed.");
72
+
73
+ Status = OrderStatus.Confirmed;
74
+ }
75
+
76
+ public void Ship()
77
+ {
78
+ if (Status != OrderStatus.Confirmed)
79
+ throw new InvalidOperationException("Only confirmed orders can be shipped.");
80
+
81
+ Status = OrderStatus.Shipped;
82
+ }
83
+
84
+ public void Complete()
85
+ {
86
+ if (Status != OrderStatus.Shipped)
87
+ throw new InvalidOperationException("Only shipped orders can be completed.");
88
+
89
+ Status = OrderStatus.Completed;
90
+ }
91
+
92
+ public void Cancel()
93
+ {
94
+ if (Status == OrderStatus.Completed)
95
+ throw new InvalidOperationException("Completed orders cannot be cancelled.");
96
+
97
+ Status = OrderStatus.Cancelled;
98
+ }
99
+
100
+ public void AddNotes(string notes)
101
+ {
102
+ Notes = notes;
103
+ }
104
+ }
105
+
106
+ /// <summary>
107
+ /// Order status enum.
108
+ /// </summary>
109
+ public enum OrderStatus
110
+ {
111
+ Pending = 0,
112
+ Confirmed = 1,
113
+ Shipped = 2,
114
+ Completed = 3,
115
+ Cancelled = 4
116
+ }
@@ -0,0 +1,64 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+ using Microsoft.EntityFrameworkCore.Metadata.Builders;
3
+ using {{ProjectName}}.Domain.Entities;
4
+ using SmartStack.Infrastructure.Persistence.Configurations;
5
+
6
+ namespace {{ProjectName}}.Infrastructure.Persistence.Configurations;
7
+
8
+ /// <summary>
9
+ /// EF Core configuration for the Order entity.
10
+ ///
11
+ /// NOTE: The table is created in the 'extensions' schema as defined by
12
+ /// ExtensionsDbContext.HasDefaultSchema(SchemaConstants.Extensions).
13
+ /// </summary>
14
+ public class OrderConfiguration : IEntityTypeConfiguration<Order>
15
+ {
16
+ public void Configure(EntityTypeBuilder<Order> builder)
17
+ {
18
+ // Table name with domain prefix (following SmartStack conventions)
19
+ // Use a prefix that makes sense for your domain
20
+ builder.ToTable("biz_Orders", SchemaConstants.Extensions);
21
+
22
+ // Primary key
23
+ builder.HasKey(e => e.Id);
24
+
25
+ // Properties
26
+ builder.Property(e => e.OrderNumber)
27
+ .IsRequired()
28
+ .HasMaxLength(50);
29
+
30
+ builder.Property(e => e.Status)
31
+ .IsRequired();
32
+
33
+ builder.Property(e => e.TotalAmount)
34
+ .HasPrecision(18, 2);
35
+
36
+ builder.Property(e => e.OrderDate)
37
+ .IsRequired();
38
+
39
+ builder.Property(e => e.Notes)
40
+ .HasMaxLength(1000);
41
+
42
+ // CustomerId is a GUID FK to Core.auth_Users
43
+ // IMPORTANT: We do NOT create a navigation property or FK constraint
44
+ // because the User table is in a different DbContext (CoreDbContext)
45
+ builder.Property(e => e.CustomerId)
46
+ .IsRequired();
47
+
48
+ // NOTE: No .HasOne() or navigation property to User!
49
+ // Use ICoreDataService.GetUserByIdAsync() to fetch user data
50
+
51
+ // Indexes
52
+ builder.HasIndex(e => e.OrderNumber)
53
+ .IsUnique();
54
+
55
+ builder.HasIndex(e => e.CustomerId);
56
+
57
+ builder.HasIndex(e => e.Status);
58
+
59
+ builder.HasIndex(e => e.OrderDate);
60
+
61
+ // Query filter for soft delete (if using BaseAuditableEntity)
62
+ builder.HasQueryFilter(e => !e.IsDeleted);
63
+ }
64
+ }
@@ -0,0 +1,146 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+ using SmartStack.Application.Common.Interfaces;
3
+ using {{ProjectName}}.Application.Common.Interfaces;
4
+ using {{ProjectName}}.Domain.Entities;
5
+
6
+ namespace {{ProjectName}}.Infrastructure.Services;
7
+
8
+ /// <summary>
9
+ /// Example service demonstrating how to use ICoreDataService
10
+ /// to fetch Core entity data (User, Role, etc.) from Extensions context.
11
+ /// </summary>
12
+ public class OrderService : IOrderService
13
+ {
14
+ private readonly IExtensionsDbContext _context;
15
+ private readonly ICoreDataService _coreDataService;
16
+
17
+ public OrderService(
18
+ IExtensionsDbContext context,
19
+ ICoreDataService coreDataService)
20
+ {
21
+ _context = context;
22
+ _coreDataService = coreDataService;
23
+ }
24
+
25
+ /// <summary>
26
+ /// Gets an order by ID, including customer information from Core.
27
+ /// </summary>
28
+ public async Task<OrderWithCustomerDto?> GetOrderWithCustomerAsync(
29
+ Guid orderId,
30
+ CancellationToken cancellationToken = default)
31
+ {
32
+ // 1. Get the order from Extensions context
33
+ var order = await _context.Orders
34
+ .AsNoTracking()
35
+ .FirstOrDefaultAsync(o => o.Id == orderId, cancellationToken);
36
+
37
+ if (order == null)
38
+ return null;
39
+
40
+ // 2. Use ICoreDataService to fetch customer info from Core context
41
+ // This is the correct way to access Core entities from Extensions!
42
+ var customer = await _coreDataService.GetUserBasicInfoAsync(
43
+ order.CustomerId,
44
+ cancellationToken);
45
+
46
+ // 3. Combine the data
47
+ return new OrderWithCustomerDto
48
+ {
49
+ Id = order.Id,
50
+ OrderNumber = order.OrderNumber,
51
+ Status = order.Status.ToString(),
52
+ TotalAmount = order.TotalAmount,
53
+ OrderDate = order.OrderDate,
54
+ CustomerId = order.CustomerId,
55
+ CustomerEmail = customer?.Email ?? "Unknown",
56
+ CustomerName = customer?.DisplayName ?? "Unknown"
57
+ };
58
+ }
59
+
60
+ /// <summary>
61
+ /// Gets all orders for a customer.
62
+ /// </summary>
63
+ public async Task<IReadOnlyList<OrderDto>> GetOrdersByCustomerAsync(
64
+ Guid customerId,
65
+ CancellationToken cancellationToken = default)
66
+ {
67
+ // First verify the customer exists in Core
68
+ var customer = await _coreDataService.GetUserBasicInfoAsync(
69
+ customerId,
70
+ cancellationToken);
71
+
72
+ if (customer == null)
73
+ throw new InvalidOperationException($"Customer {customerId} not found.");
74
+
75
+ // Get orders from Extensions context
76
+ return await _context.Orders
77
+ .AsNoTracking()
78
+ .Where(o => o.CustomerId == customerId)
79
+ .OrderByDescending(o => o.OrderDate)
80
+ .Select(o => new OrderDto
81
+ {
82
+ Id = o.Id,
83
+ OrderNumber = o.OrderNumber,
84
+ Status = o.Status.ToString(),
85
+ TotalAmount = o.TotalAmount,
86
+ OrderDate = o.OrderDate
87
+ })
88
+ .ToListAsync(cancellationToken);
89
+ }
90
+
91
+ /// <summary>
92
+ /// Creates a new order.
93
+ /// </summary>
94
+ public async Task<Guid> CreateOrderAsync(
95
+ string orderNumber,
96
+ Guid customerId,
97
+ decimal totalAmount,
98
+ CancellationToken cancellationToken = default)
99
+ {
100
+ // Validate that the customer exists in Core before creating order
101
+ var customer = await _coreDataService.GetUserByIdAsync(
102
+ customerId,
103
+ cancellationToken);
104
+
105
+ if (customer == null)
106
+ throw new InvalidOperationException($"Customer {customerId} not found.");
107
+
108
+ if (!customer.IsActive)
109
+ throw new InvalidOperationException("Cannot create order for inactive customer.");
110
+
111
+ // Create the order in Extensions context
112
+ var order = Order.Create(orderNumber, customerId, totalAmount);
113
+
114
+ _context.Orders.Add(order);
115
+ await _context.SaveChangesAsync(cancellationToken);
116
+
117
+ return order.Id;
118
+ }
119
+ }
120
+
121
+ // === DTOs ===
122
+
123
+ public record OrderDto
124
+ {
125
+ public Guid Id { get; init; }
126
+ public string OrderNumber { get; init; } = null!;
127
+ public string Status { get; init; } = null!;
128
+ public decimal TotalAmount { get; init; }
129
+ public DateTime OrderDate { get; init; }
130
+ }
131
+
132
+ public record OrderWithCustomerDto : OrderDto
133
+ {
134
+ public Guid CustomerId { get; init; }
135
+ public string CustomerEmail { get; init; } = null!;
136
+ public string CustomerName { get; init; } = null!;
137
+ }
138
+
139
+ // === Interface ===
140
+
141
+ public interface IOrderService
142
+ {
143
+ Task<OrderWithCustomerDto?> GetOrderWithCustomerAsync(Guid orderId, CancellationToken cancellationToken = default);
144
+ Task<IReadOnlyList<OrderDto>> GetOrdersByCustomerAsync(Guid customerId, CancellationToken cancellationToken = default);
145
+ Task<Guid> CreateOrderAsync(string orderNumber, Guid customerId, decimal totalAmount, CancellationToken cancellationToken = default);
146
+ }
@@ -0,0 +1,41 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+ using {{ProjectName}}.Application.Common.Interfaces;
3
+ using SmartStack.Infrastructure.Persistence.Configurations;
4
+
5
+ namespace {{ProjectName}}.Infrastructure.Persistence;
6
+
7
+ /// <summary>
8
+ /// DbContext for client-specific entities (schema: extensions).
9
+ ///
10
+ /// This context manages all entities specific to your project.
11
+ /// SmartStack Core entities (User, Role, etc.) are managed separately
12
+ /// by CoreDbContext from the SmartStack NuGet package.
13
+ ///
14
+ /// IMPORTANT: To reference Core entities (User, Role, etc.):
15
+ /// - Store only the GUID foreign key (e.g., CreatedByUserId)
16
+ /// - Use ICoreDataService to fetch the related entity data
17
+ /// - Do NOT create navigation properties to Core entities
18
+ /// </summary>
19
+ public class ExtensionsDbContext : DbContext, IExtensionsDbContext
20
+ {
21
+ public ExtensionsDbContext(DbContextOptions<ExtensionsDbContext> options)
22
+ : base(options)
23
+ {
24
+ }
25
+
26
+ // === YOUR ENTITIES ===
27
+ // Add your DbSet properties here. Example:
28
+ // public DbSet<Order> Orders => Set<Order>();
29
+ // public DbSet<Product> Products => Set<Product>();
30
+
31
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
32
+ {
33
+ base.OnModelCreating(modelBuilder);
34
+
35
+ // All client entities go into the 'extensions' schema
36
+ modelBuilder.HasDefaultSchema(SchemaConstants.Extensions);
37
+
38
+ // Load entity configurations from this assembly
39
+ modelBuilder.ApplyConfigurationsFromAssembly(typeof(ExtensionsDbContext).Assembly);
40
+ }
41
+ }
@@ -0,0 +1,22 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+
3
+ namespace {{ProjectName}}.Application.Common.Interfaces;
4
+
5
+ /// <summary>
6
+ /// Interface for Extensions DbContext (client-specific entities).
7
+ ///
8
+ /// This interface provides access to all entities specific to your project.
9
+ /// For Core entities (User, Role, Permission, etc.), use ICoreDataService.
10
+ /// </summary>
11
+ public interface IExtensionsDbContext
12
+ {
13
+ // === YOUR ENTITIES ===
14
+ // Add DbSet properties for your entities here. Example:
15
+ // DbSet<Order> Orders { get; }
16
+ // DbSet<Product> Products { get; }
17
+
18
+ /// <summary>
19
+ /// Saves all changes made in this context to the database.
20
+ /// </summary>
21
+ Task<int> SaveChangesAsync(CancellationToken cancellationToken = default);
22
+ }
@@ -0,0 +1,47 @@
1
+ using Microsoft.EntityFrameworkCore;
2
+ using SmartStack.Api.Extensions;
3
+ using {{ProjectName}}.Infrastructure;
4
+ using {{ProjectName}}.Infrastructure.Persistence;
5
+ using {{ProjectName}}.Application;
6
+
7
+ var builder = WebApplication.CreateBuilder(args);
8
+
9
+ // ===================================================================
10
+ // 1. Add SmartStack Core services (from NuGet package)
11
+ // ===================================================================
12
+ builder.Services.AddSmartStack(builder.Configuration, options =>
13
+ {
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
+ }
40
+
41
+ // ===================================================================
42
+ // 4. SmartStack middleware & endpoints
43
+ // ===================================================================
44
+ app.UseSmartStack();
45
+ app.MapSmartStack();
46
+
47
+ app.Run();
@@ -0,0 +1,79 @@
1
+ # SmartStack Client Project Templates
2
+
3
+ These templates are used by the SmartStack CLI to generate new client projects.
4
+
5
+ ## Template Files
6
+
7
+ | File | Description | Destination |
8
+ |------|-------------|-------------|
9
+ | `ExtensionsDbContext.cs.template` | DbContext for client entities | `{ProjectName}.Infrastructure/Persistence/` |
10
+ | `IExtensionsDbContext.cs.template` | Interface for ExtensionsDbContext | `{ProjectName}.Application/Common/Interfaces/` |
11
+ | `DependencyInjection.Infrastructure.cs.template` | DI configuration for Infrastructure | `{ProjectName}.Infrastructure/` |
12
+ | `Program.cs.template` | API entry point with migration order | `{ProjectName}.Api/` |
13
+ | `DesignTimeExtensionsDbContextFactory.cs.template` | Factory for EF Core CLI tools | `{ProjectName}.Infrastructure/Persistence/` |
14
+ | `ExampleEntity.cs.template` | Example entity with FK to Core | `{ProjectName}.Domain/Entities/` (optional) |
15
+ | `ExampleService.cs.template` | Example service using ICoreDataService | `{ProjectName}.Infrastructure/Services/` (optional) |
16
+ | `ExampleEntityConfiguration.cs.template` | Example EF Core configuration | `{ProjectName}.Infrastructure/Persistence/Configurations/` (optional) |
17
+
18
+ ## Placeholders
19
+
20
+ The following placeholders are replaced during project generation:
21
+
22
+ | Placeholder | Description | Example |
23
+ |-------------|-------------|---------|
24
+ | `{{ProjectName}}` | PascalCase project name | `MyCompany` |
25
+
26
+ ## Architecture Overview
27
+
28
+ ### Dual DbContext Pattern
29
+
30
+ SmartStack uses two separate DbContexts:
31
+
32
+ 1. **CoreDbContext** (from SmartStack NuGet package)
33
+ - Schema: `core`
34
+ - Manages: Users, Roles, Permissions, Navigation, etc.
35
+ - Migrations: `core.__EFMigrationsHistory`
36
+
37
+ 2. **ExtensionsDbContext** (client project)
38
+ - Schema: `extensions`
39
+ - Manages: Client-specific entities
40
+ - Migrations: `extensions.__EFMigrationsHistory`
41
+
42
+ ### FK References to Core Entities
43
+
44
+ When your entities need to reference Core entities (User, Role, etc.):
45
+
46
+ ```csharp
47
+ // IN YOUR ENTITY - Store GUID only
48
+ public Guid CustomerId { get; private set; } // FK to User
49
+
50
+ // IN YOUR SERVICE - Use ICoreDataService
51
+ var user = await _coreDataService.GetUserByIdAsync(entity.CustomerId);
52
+ ```
53
+
54
+ **DO NOT** create navigation properties to Core entities, as ExtensionsDbContext doesn't know about them.
55
+
56
+ ### Migration Order
57
+
58
+ Migrations must be applied in order:
59
+
60
+ 1. Core migrations first (SmartStack platform tables)
61
+ 2. Extensions migrations second (client tables that may reference Core)
62
+
63
+ This is handled automatically in `Program.cs.template`.
64
+
65
+ ## Usage
66
+
67
+ ```bash
68
+ # Create new project
69
+ smartstack init MyProject
70
+
71
+ # Add entity to Extensions
72
+ smartstack scaffold entity Order --context extensions
73
+
74
+ # Create migration
75
+ dotnet ef migrations add ext_v1.0.0_001_AddOrders --context ExtensionsDbContext
76
+
77
+ # Apply migrations
78
+ dotnet ef database update
79
+ ```
@@ -27,15 +27,17 @@ Edit `ralph.config.yaml` to customize:
27
27
 
28
28
  Ralph **requires** these MCP servers to function:
29
29
 
30
- 1. **context7** - Library documentation
31
- ```bash
32
- claude mcp add context7
33
- ```
30
+ ### 1. Download MCP packages
31
+ ```bash
32
+ npm install -g @atlashub/smartstack-mcp
33
+ npm install -g @upstash/context7-mcp
34
+ ```
34
35
 
35
- 2. **smartstack** - Validation and scaffolding
36
- ```bash
37
- claude mcp add smartstack
38
- ```
36
+ ### 2. Register in Claude Code
37
+ ```bash
38
+ claude mcp add smartstack -- npx @atlashub/smartstack-mcp
39
+ claude mcp add context7 -- npx @upstash/context7-mcp
40
+ ```
39
41
 
40
42
  ## Usage
41
43
 
@@ -9,12 +9,12 @@ mcp:
9
9
  required:
10
10
  - name: context7
11
11
  description: "Library documentation and code examples"
12
- install_command: "claude mcp add context7"
12
+ install_command: "npm install -g @upstash/context7-mcp && claude mcp add context7 -- npx @upstash/context7-mcp"
13
13
  health_check: true
14
14
 
15
15
  - name: smartstack
16
16
  description: "SmartStack validation and scaffolding"
17
- install_command: "claude mcp add smartstack"
17
+ install_command: "npm install -g @atlashub/smartstack-mcp && claude mcp add smartstack -- npx @atlashub/smartstack-mcp"
18
18
  health_check: true
19
19
 
20
20
  # Behavior when MCP is unavailable