@atlashub/smartstack-mcp 1.10.0 → 1.13.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/dist/index.js CHANGED
@@ -1822,6 +1822,10 @@ var scaffoldExtensionTool = {
1822
1822
  type: "boolean",
1823
1823
  description: "For feature type: generate repository pattern"
1824
1824
  },
1825
+ withSeedData: {
1826
+ type: "boolean",
1827
+ description: "For entity type: generate centralized SeedData file in Seeding/Data/{Domain}/"
1828
+ },
1825
1829
  entityProperties: {
1826
1830
  type: "array",
1827
1831
  items: {
@@ -2346,6 +2350,119 @@ public class {{name}}Configuration : IEntityTypeConfiguration<{{name}}>
2346
2350
  result.instructions.push("- CreatedAt, UpdatedAt, CreatedBy, UpdatedBy (audit)");
2347
2351
  result.instructions.push("- IsDeleted, DeletedAt, DeletedBy (soft delete)");
2348
2352
  result.instructions.push("- RowVersion (concurrency)");
2353
+ if (options?.withSeedData) {
2354
+ result.instructions.push("");
2355
+ result.instructions.push("### Seed Data");
2356
+ await scaffoldSeedData(name, options, structure, config, result, dryRun);
2357
+ }
2358
+ }
2359
+ async function scaffoldSeedData(name, options, structure, config, result, dryRun = false) {
2360
+ const tablePrefix = options?.tablePrefix || "ref_";
2361
+ const domainMap = {
2362
+ "auth_": "Authorization",
2363
+ "nav_": "Navigation",
2364
+ "usr_": "User",
2365
+ "wkf_": "Communications",
2366
+ "cfg_": "Configuration",
2367
+ "ai_": "AI",
2368
+ "entra_": "Entra",
2369
+ "ref_": "Reference",
2370
+ "support_": "Support",
2371
+ "loc_": "Localization"
2372
+ };
2373
+ const domain = options?.seedDataDomain || domainMap[tablePrefix] || "Reference";
2374
+ const isSystemEntity = options?.isSystemEntity || false;
2375
+ const seedDataTemplate = `using SmartStack.Domain.{{domainNamespace}};
2376
+
2377
+ namespace SmartStack.Infrastructure.Persistence.Seeding.Data.{{domain}};
2378
+
2379
+ /// <summary>
2380
+ /// Donnees seed pour {{name}}.
2381
+ /// Centralise les IDs et donnees d'initialisation.
2382
+ /// </summary>
2383
+ public static class {{name}}SeedData
2384
+ {
2385
+ // ============================================================
2386
+ // IDs - Documenter chaque ID avec son role
2387
+ // ============================================================
2388
+
2389
+ /// <summary>ID exemple - A remplacer par vos IDs</summary>
2390
+ public static readonly Guid ExampleId = Guid.Parse("{{exampleGuid}}");
2391
+
2392
+ // ============================================================
2393
+ // CODES / CONSTANTS
2394
+ // ============================================================
2395
+
2396
+ public const string ExampleCode = "example";
2397
+
2398
+ // ============================================================
2399
+ // SEED DATA
2400
+ // ============================================================
2401
+
2402
+ /// <summary>
2403
+ /// Retourne toutes les donnees seed pour {{name}}.
2404
+ /// Appel\xE9 depuis {{name}}Configuration.HasData()
2405
+ /// </summary>
2406
+ public static object[] GetSeedData()
2407
+ {
2408
+ var seedDate = SeedConstants.SeedDate;
2409
+
2410
+ return new object[]
2411
+ {
2412
+ // Exemple - A remplacer par vos donnees
2413
+ new
2414
+ {
2415
+ Id = ExampleId,
2416
+ {{#unless isSystemEntity}}
2417
+ TenantId = (Guid?)null, // Seed data systeme sans tenant
2418
+ {{/unless}}
2419
+ Code = ExampleCode,
2420
+ // TODO: Ajouter les proprietes specifiques
2421
+ IsDeleted = false,
2422
+ CreatedAt = seedDate
2423
+ }
2424
+ };
2425
+ }
2426
+ }
2427
+ `;
2428
+ const exampleGuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
2429
+ const r = Math.random() * 16 | 0;
2430
+ const v = c === "x" ? r : r & 3 | 8;
2431
+ return v.toString(16);
2432
+ });
2433
+ const context = {
2434
+ name,
2435
+ domain,
2436
+ domainNamespace: domain,
2437
+ isSystemEntity,
2438
+ exampleGuid
2439
+ };
2440
+ const seedDataContent = Handlebars.compile(seedDataTemplate)(context);
2441
+ const projectRoot = config.smartstack.projectPath;
2442
+ const infraPath = structure.infrastructure || path8.join(projectRoot, "Infrastructure");
2443
+ const seedDataPath = path8.join(infraPath, "Persistence", "Seeding", "Data", domain);
2444
+ const seedDataFilePath = path8.join(seedDataPath, `${name}SeedData.cs`);
2445
+ validatePathSecurity(seedDataFilePath, projectRoot);
2446
+ if (!dryRun) {
2447
+ await ensureDirectory(seedDataPath);
2448
+ await writeText(seedDataFilePath, seedDataContent);
2449
+ }
2450
+ result.files.push({ path: seedDataFilePath, content: seedDataContent, type: "created" });
2451
+ result.instructions.push(`SeedData file generated in Seeding/Data/${domain}/`);
2452
+ result.instructions.push("");
2453
+ result.instructions.push("Update your Configuration to use centralized SeedData:");
2454
+ result.instructions.push("```csharp");
2455
+ result.instructions.push(`// In ${name}Configuration.cs`);
2456
+ result.instructions.push(`using SmartStack.Infrastructure.Persistence.Seeding.Data.${domain};`);
2457
+ result.instructions.push("");
2458
+ result.instructions.push(`builder.HasData(${name}SeedData.GetSeedData());`);
2459
+ result.instructions.push("```");
2460
+ result.instructions.push("");
2461
+ result.instructions.push("Pattern to follow:");
2462
+ result.instructions.push("1. Define public static readonly Guid IDs");
2463
+ result.instructions.push("2. Define const string codes");
2464
+ result.instructions.push("3. Implement GetSeedData() returning object[]");
2465
+ result.instructions.push("4. Reference other SeedData IDs for foreign keys");
2349
2466
  }
2350
2467
  async function scaffoldController(name, options, structure, config, result, dryRun = false) {
2351
2468
  const namespace = options?.namespace || `${config.conventions.namespaces.api}.Controllers`;
@@ -3658,7 +3775,7 @@ async function handleSuggestMigration(args, config) {
3658
3775
  async function findExistingMigrations(structure, config, context) {
3659
3776
  const migrations = [];
3660
3777
  const infraPath = structure.infrastructure || path10.join(config.smartstack.projectPath, "Infrastructure");
3661
- const migrationsPath = path10.join(infraPath, "Migrations");
3778
+ const migrationsPath = path10.join(infraPath, "Persistence", "Migrations");
3662
3779
  try {
3663
3780
  const migrationFiles = await findFiles("*.cs", { cwd: migrationsPath });
3664
3781
  const migrationPattern = /^(\w+)_v(\d+\.\d+\.\d+)_(\d+)_(\w+)\.cs$/;
@@ -3705,7 +3822,6 @@ function compareVersions2(a, b) {
3705
3822
  }
3706
3823
 
3707
3824
  // src/tools/generate-permissions.ts
3708
- import Handlebars2 from "handlebars";
3709
3825
  import path11 from "path";
3710
3826
  var HTTP_METHOD_TO_ACTION = {
3711
3827
  "GET": "read",
@@ -3722,17 +3838,21 @@ var generatePermissionsTool = {
3722
3838
  name: "generate_permissions",
3723
3839
  description: `Generate RBAC permissions for SmartStack controllers.
3724
3840
 
3725
- Automatically creates permissions following the convention: {navRoute}.{action}
3841
+ Analyzes NavRoute attributes and outputs HasData() C# code to add to PermissionConfiguration.cs.
3842
+
3843
+ IMPORTANT: This tool does NOT generate migrations with raw SQL (forbidden by SmartStack conventions).
3844
+ Instead, it outputs HasData() code that must be manually added to the Configuration file.
3726
3845
 
3727
3846
  Example:
3728
3847
  navRoute: "platform.administration.entra"
3729
- Generates:
3848
+ Outputs HasData() code for:
3849
+ - platform.administration.entra.*
3730
3850
  - platform.administration.entra.read
3731
3851
  - platform.administration.entra.create
3732
3852
  - platform.administration.entra.update
3733
3853
  - platform.administration.entra.delete
3734
3854
 
3735
- Can also generate EF Core migration to seed permissions in database.`,
3855
+ After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <MigrationName>`,
3736
3856
  inputSchema: {
3737
3857
  type: "object",
3738
3858
  properties: {
@@ -3750,15 +3870,10 @@ Can also generate EF Core migration to seed permissions in database.`,
3750
3870
  default: true,
3751
3871
  description: "Include standard CRUD actions (read, create, update, delete)"
3752
3872
  },
3753
- generateMigration: {
3873
+ includeWildcard: {
3754
3874
  type: "boolean",
3755
3875
  default: true,
3756
- description: "Generate EF Core migration to seed permissions in database"
3757
- },
3758
- dryRun: {
3759
- type: "boolean",
3760
- default: false,
3761
- description: "Preview without writing files or creating migration"
3876
+ description: "Include wildcard permission (e.g., personal.myspace.tenants.*)"
3762
3877
  }
3763
3878
  }
3764
3879
  }
@@ -3769,8 +3884,7 @@ async function handleGeneratePermissions(args, config) {
3769
3884
  navRoute: args.navRoute,
3770
3885
  actions: args.actions || [],
3771
3886
  includeStandardActions: args.includeStandardActions !== false,
3772
- generateMigration: args.generateMigration !== false,
3773
- dryRun: args.dryRun === true
3887
+ includeWildcard: args.includeWildcard !== false
3774
3888
  };
3775
3889
  const structure = await findSmartStackStructure(config.smartstack.projectPath);
3776
3890
  if (!structure) {
@@ -3782,16 +3896,17 @@ async function handleGeneratePermissions(args, config) {
3782
3896
  permissions = generatePermissionsForNavRoute(
3783
3897
  options.navRoute,
3784
3898
  options.actions || [],
3785
- options.includeStandardActions || false
3899
+ options.includeStandardActions || false,
3900
+ options.includeWildcard || false
3786
3901
  );
3787
- report = `## Permissions Generated for NavRoute: ${options.navRoute}
3902
+ report = `## Permissions for NavRoute: ${options.navRoute}
3788
3903
 
3789
3904
  `;
3790
3905
  report += formatPermissionsReport(permissions);
3791
3906
  } else {
3792
3907
  const scannedPermissions = await scanControllersForPermissions(structure.api || structure.root);
3793
3908
  permissions = scannedPermissions;
3794
- report = `## Permissions Generated from All Controllers
3909
+ report = `## Permissions from All Controllers
3795
3910
 
3796
3911
  `;
3797
3912
  report += `Total controllers scanned: ${getUniqueNavRouteCount(permissions)}
@@ -3801,53 +3916,51 @@ async function handleGeneratePermissions(args, config) {
3801
3916
  `;
3802
3917
  report += formatPermissionsReport(permissions);
3803
3918
  }
3804
- if (options.generateMigration && !options.dryRun) {
3805
- const migrationResult = await generatePermissionMigration(
3806
- structure.api || structure.root,
3807
- permissions,
3808
- config
3809
- );
3810
- report += `
3919
+ report += `
3811
3920
 
3812
- ## Migration Generated
3921
+ ## HasData() Code for PermissionConfiguration.cs
3813
3922
 
3814
3923
  `;
3815
- report += `File: ${migrationResult.filePath}
3924
+ report += `\u26A0\uFE0F **IMPORTANT**: Do NOT use migrationBuilder.Sql() - it's forbidden by SmartStack conventions.
3816
3925
  `;
3817
- report += `Migration name: ${migrationResult.migrationName}
3926
+ report += `Add this code to \`PermissionConfiguration.cs\` in the HasData() section, then create a migration.
3818
3927
 
3819
3928
  `;
3820
- report += `### Next Steps
3929
+ report += generateHasDataCode(permissions, options.navRoute || "custom");
3930
+ report += `
3931
+
3932
+ ### Next Steps
3821
3933
 
3822
3934
  `;
3823
- report += `1. Review the generated migration
3824
- `;
3825
- report += `2. Run: \`dotnet ef database update\`
3935
+ report += `1. Add the module ID variable in GetSeedData() method
3826
3936
  `;
3827
- report += `3. Verify permissions in auth_Permissions table
3937
+ report += `2. Add the HasData entries to the return array
3828
3938
  `;
3829
- } else if (options.dryRun) {
3830
- report += `
3831
-
3832
- ## Dry Run Mode
3833
-
3939
+ report += `3. Run: \`dotnet ef migrations add <MigrationName> -o Persistence/Migrations\`
3834
3940
  `;
3835
- report += `No files were created. Remove 'dryRun: true' to generate migration.
3941
+ report += `4. Run: \`dotnet ef database update\`
3836
3942
  `;
3837
- }
3838
3943
  return report;
3839
3944
  } catch (error) {
3840
3945
  logger.error("Error generating permissions:", error);
3841
3946
  throw error;
3842
3947
  }
3843
3948
  }
3844
- function generatePermissionsForNavRoute(navRoute, customActions, includeStandardActions) {
3949
+ function generatePermissionsForNavRoute(navRoute, customActions, includeStandardActions, includeWildcard = true) {
3845
3950
  const permissions = [];
3846
3951
  const parts = navRoute.split(".");
3847
3952
  const context = parts[0];
3848
3953
  if (parts.length < 3) {
3849
3954
  throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: context.application.module`);
3850
3955
  }
3956
+ if (includeWildcard) {
3957
+ permissions.push({
3958
+ code: `${navRoute}.*`,
3959
+ name: formatPermissionName(navRoute, "Full Access"),
3960
+ description: `Full ${parts[parts.length - 1]} management`,
3961
+ category: context
3962
+ });
3963
+ }
3851
3964
  const actions = includeStandardActions ? [...STANDARD_ACTIONS, ...customActions] : customActions;
3852
3965
  for (const action of actions) {
3853
3966
  const code = `${navRoute}.${action}`;
@@ -3986,87 +4099,54 @@ function getUniqueNavRouteCount(permissions) {
3986
4099
  );
3987
4100
  return navRoutes.size;
3988
4101
  }
3989
- async function generatePermissionMigration(backendRoot, permissions, config) {
3990
- const templatePath = path11.join(
3991
- process.cwd(),
3992
- "templates",
3993
- "migrations",
3994
- "seed-permissions.cs.hbs"
3995
- );
3996
- let template;
3997
- try {
3998
- template = await readText(templatePath);
3999
- } catch {
4000
- template = getSeedPermissionsTemplate();
4001
- }
4002
- const handlebars = Handlebars2.create();
4003
- const compiled = handlebars.compile(template);
4004
- const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[-:T.]/g, "").slice(0, 14);
4005
- const migrationName = `SeedPermissions_${timestamp}`;
4006
- const content = compiled({
4007
- migrationName,
4008
- permissions,
4009
- timestamp
4010
- });
4011
- const migrationsPath = path11.join(
4012
- backendRoot,
4013
- "Infrastructure",
4014
- "Data",
4015
- "Migrations",
4016
- "Core"
4017
- );
4018
- await ensureDirectory(migrationsPath);
4019
- const filePath = path11.join(migrationsPath, `${migrationName}.cs`);
4020
- validatePathSecurity(filePath, config.smartstack.projectPath);
4021
- await writeText(filePath, content);
4022
- logger.info(`Generated permission migration: ${filePath}`);
4023
- return {
4024
- filePath,
4025
- migrationName
4026
- };
4027
- }
4028
- function getSeedPermissionsTemplate() {
4029
- return `using Microsoft.EntityFrameworkCore.Migrations;
4030
-
4031
- namespace SmartStack.Infrastructure.Data.Migrations.Core;
4102
+ function generateHasDataCode(permissions, navRoute) {
4103
+ const parts = navRoute.split(".");
4104
+ const moduleName = parts.length >= 3 ? parts[parts.length - 1] : "custom";
4105
+ const moduleVarName = `${moduleName}ModuleId`;
4106
+ let code = "```csharp\n";
4107
+ code += `// 1. Add module ID variable (get from NavigationModuleSeedData.cs)
4108
+ `;
4109
+ code += `var ${moduleVarName} = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); // TODO: Replace with actual ID
4032
4110
 
4033
- /// <summary>
4034
- /// Seed permissions generated from NavRoute controllers
4035
- /// Generated on {{timestamp}}
4036
- /// </summary>
4037
- public partial class {{migrationName}} : Migration
4038
- {
4039
- protected override void Up(MigrationBuilder migrationBuilder)
4040
- {
4041
- // Insert permissions
4042
- {{#each permissions}}
4043
- migrationBuilder.Sql(@"
4044
- IF NOT EXISTS (SELECT 1 FROM core.auth_Permissions WHERE Code = '{{code}}')
4045
- BEGIN
4046
- INSERT INTO core.auth_Permissions (Id, Code, Name, Description, IsDeleted, CreatedAt, UpdatedAt)
4047
- VALUES (
4048
- NEWID(),
4049
- '{{code}}',
4050
- '{{name}}',
4051
- '{{description}}',
4052
- 0,
4053
- GETUTCDATE(),
4054
- GETUTCDATE()
4055
- );
4056
- END
4057
- ");
4058
- {{/each}}
4059
- }
4060
-
4061
- protected override void Down(MigrationBuilder migrationBuilder)
4062
- {
4063
- // Remove seeded permissions
4064
- {{#each permissions}}
4065
- migrationBuilder.Sql(@"DELETE FROM core.auth_Permissions WHERE Code = '{{code}}'");
4066
- {{/each}}
4111
+ `;
4112
+ code += `// 2. Add these entries to the HasData() return array:
4113
+ `;
4114
+ for (const perm of permissions) {
4115
+ const isWildcard = perm.code.endsWith(".*");
4116
+ const action = perm.code.split(".").pop();
4117
+ const guidPlaceholder = generatePlaceholderGuid();
4118
+ if (isWildcard) {
4119
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, IsWildcard = true, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
4120
+ `;
4121
+ } else {
4122
+ const actionEnum = getActionEnum(action || "read");
4123
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, Action = PermissionAction.${actionEnum}, IsWildcard = false, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
4124
+ `;
4067
4125
  }
4068
- }
4126
+ }
4127
+ code += "```\n";
4128
+ code += "\n\u26A0\uFE0F **IMPORTANT**: Replace all GUIDs with randomly generated ones using:\n";
4129
+ code += "```powershell\n";
4130
+ code += `1..${permissions.length} | ForEach-Object { [guid]::NewGuid().ToString() }
4069
4131
  `;
4132
+ code += "```\n";
4133
+ return code;
4134
+ }
4135
+ function generatePlaceholderGuid() {
4136
+ return "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
4137
+ }
4138
+ function getActionEnum(action) {
4139
+ const actionMap = {
4140
+ "read": "Read",
4141
+ "create": "Create",
4142
+ "update": "Update",
4143
+ "delete": "Delete",
4144
+ "assign": "Assign",
4145
+ "execute": "Execute",
4146
+ "export": "Export",
4147
+ "import": "Import"
4148
+ };
4149
+ return actionMap[action.toLowerCase()] || action.charAt(0).toUpperCase() + action.slice(1);
4070
4150
  }
4071
4151
  async function readDirectoryRecursive(dir) {
4072
4152
  const files = [];
@@ -4086,7 +4166,7 @@ async function readDirectoryRecursive(dir) {
4086
4166
  }
4087
4167
 
4088
4168
  // src/tools/scaffold-tests.ts
4089
- import Handlebars3 from "handlebars";
4169
+ import Handlebars2 from "handlebars";
4090
4170
  import path12 from "path";
4091
4171
  var scaffoldTestsTool = {
4092
4172
  name: "scaffold_tests",
@@ -4166,15 +4246,15 @@ var scaffoldTestsTool = {
4166
4246
  required: ["target", "name"]
4167
4247
  }
4168
4248
  };
4169
- Handlebars3.registerHelper("pascalCase", (str) => {
4249
+ Handlebars2.registerHelper("pascalCase", (str) => {
4170
4250
  if (!str) return "";
4171
4251
  return str.charAt(0).toUpperCase() + str.slice(1);
4172
4252
  });
4173
- Handlebars3.registerHelper("camelCase", (str) => {
4253
+ Handlebars2.registerHelper("camelCase", (str) => {
4174
4254
  if (!str) return "";
4175
4255
  return str.charAt(0).toLowerCase() + str.slice(1);
4176
4256
  });
4177
- Handlebars3.registerHelper("unless", function(conditional, options) {
4257
+ Handlebars2.registerHelper("unless", function(conditional, options) {
4178
4258
  if (!conditional) {
4179
4259
  return options.fn(this);
4180
4260
  }
@@ -5516,7 +5596,7 @@ async function scaffoldEntityTests(name, options, testTypes, structure, config,
5516
5596
  ...options
5517
5597
  };
5518
5598
  if (testTypes.includes("unit")) {
5519
- const content = Handlebars3.compile(entityTestTemplate)(context);
5599
+ const content = Handlebars2.compile(entityTestTemplate)(context);
5520
5600
  const testPath = path12.join(structure.root, "Tests", "Unit", "Domain", `${name}Tests.cs`);
5521
5601
  validatePathSecurity(testPath, structure.root);
5522
5602
  if (!dryRun) {
@@ -5530,7 +5610,7 @@ async function scaffoldEntityTests(name, options, testTypes, structure, config,
5530
5610
  });
5531
5611
  }
5532
5612
  if (testTypes.includes("security")) {
5533
- const securityContent = Handlebars3.compile(securityTestTemplate)({
5613
+ const securityContent = Handlebars2.compile(securityTestTemplate)({
5534
5614
  ...context,
5535
5615
  nameLower: name.charAt(0).toLowerCase() + name.slice(1),
5536
5616
  apiNamespace: config.conventions.namespaces.api
@@ -5562,7 +5642,7 @@ async function scaffoldServiceTests(name, options, testTypes, structure, config,
5562
5642
  ...options
5563
5643
  };
5564
5644
  if (testTypes.includes("unit")) {
5565
- const content = Handlebars3.compile(serviceTestTemplate)(context);
5645
+ const content = Handlebars2.compile(serviceTestTemplate)(context);
5566
5646
  const testPath = path12.join(structure.root, "Tests", "Unit", "Services", `${name}ServiceTests.cs`);
5567
5647
  validatePathSecurity(testPath, structure.root);
5568
5648
  if (!dryRun) {
@@ -5592,7 +5672,7 @@ async function scaffoldControllerTests(name, options, testTypes, structure, conf
5592
5672
  ...options
5593
5673
  };
5594
5674
  if (testTypes.includes("integration")) {
5595
- const content = Handlebars3.compile(controllerTestTemplate)(context);
5675
+ const content = Handlebars2.compile(controllerTestTemplate)(context);
5596
5676
  const testPath = path12.join(structure.root, "Tests", "Integration", "Controllers", `${name}ControllerTests.cs`);
5597
5677
  validatePathSecurity(testPath, structure.root);
5598
5678
  if (!dryRun) {
@@ -5606,7 +5686,7 @@ async function scaffoldControllerTests(name, options, testTypes, structure, conf
5606
5686
  });
5607
5687
  }
5608
5688
  if (testTypes.includes("security")) {
5609
- const securityContent = Handlebars3.compile(securityTestTemplate)(context);
5689
+ const securityContent = Handlebars2.compile(securityTestTemplate)(context);
5610
5690
  const securityPath = path12.join(structure.root, "Tests", "Security", `${name}SecurityTests.cs`);
5611
5691
  validatePathSecurity(securityPath, structure.root);
5612
5692
  if (!dryRun) {
@@ -5631,7 +5711,7 @@ async function scaffoldValidatorTests(name, options, testTypes, structure, confi
5631
5711
  ...options
5632
5712
  };
5633
5713
  if (testTypes.includes("unit")) {
5634
- const content = Handlebars3.compile(validatorTestTemplate)(context);
5714
+ const content = Handlebars2.compile(validatorTestTemplate)(context);
5635
5715
  const testPath = path12.join(structure.root, "Tests", "Unit", "Validators", `${name}ValidatorTests.cs`);
5636
5716
  validatePathSecurity(testPath, structure.root);
5637
5717
  if (!dryRun) {
@@ -5658,7 +5738,7 @@ async function scaffoldRepositoryTests(name, options, testTypes, structure, conf
5658
5738
  ...options
5659
5739
  };
5660
5740
  if (testTypes.includes("integration")) {
5661
- const content = Handlebars3.compile(repositoryTestTemplate)(context);
5741
+ const content = Handlebars2.compile(repositoryTestTemplate)(context);
5662
5742
  const testPath = path12.join(structure.root, "Tests", "Integration", "Repositories", `${name}RepositoryTests.cs`);
5663
5743
  validatePathSecurity(testPath, structure.root);
5664
5744
  if (!dryRun) {