Skip to content

Commit 8000d14

Browse files
committed
Update Version 40
1 parent 9b2d79e commit 8000d14

File tree

2 files changed

+78
-2
lines changed

2 files changed

+78
-2
lines changed

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22
<PropertyGroup>
3-
<Version>1.0.39</Version>
3+
<Version>1.0.40</Version>
44
<AssemblyVersion>$(Version).0</AssemblyVersion>
55
<FileVersion>$(Version).0</FileVersion>
66
<InformationalVersion>$(Version)</InformationalVersion>

src/QuickCode.Cli/CliApplication.cs

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,46 @@ public sealed class CliApplication
2020
private static readonly Uri HomebrewFormulaUri = new("https://raw.githubusercontent.com/QuickCodeNet/homebrew-quickcode-cli/main/Formula/quickcode-cli.rb");
2121
private readonly ConfigService _configService = new();
2222

23+
private static bool ValidateModuleName(string moduleName, out string errorMessage)
24+
{
25+
errorMessage = string.Empty;
26+
27+
if (string.IsNullOrWhiteSpace(moduleName))
28+
{
29+
errorMessage = "Module name cannot be empty.";
30+
return false;
31+
}
32+
33+
// Must start with a letter (a-z, A-Z)
34+
if (!char.IsLetter(moduleName[0]))
35+
{
36+
errorMessage = "Module name must start with a letter (a-z, A-Z).";
37+
return false;
38+
}
39+
40+
// Must contain only letters and numbers (no spaces, no special characters)
41+
if (!System.Text.RegularExpressions.Regex.IsMatch(moduleName, @"^[a-zA-Z][a-zA-Z0-9]*$"))
42+
{
43+
errorMessage = "Module name can only contain letters (a-z, A-Z) and numbers (0-9). No spaces or special characters allowed.";
44+
return false;
45+
}
46+
47+
// After a digit, the next character must be uppercase (camelCase rule)
48+
for (int i = 0; i < moduleName.Length - 1; i++)
49+
{
50+
if (char.IsDigit(moduleName[i]) && char.IsLetter(moduleName[i + 1]))
51+
{
52+
if (!char.IsUpper(moduleName[i + 1]))
53+
{
54+
errorMessage = "Module name must follow camelCase: after a digit, the next character must be uppercase (e.g., 'SmsModule2Test' not 'SmsModule2test').";
55+
return false;
56+
}
57+
}
58+
}
59+
60+
return true;
61+
}
62+
2363
private static async Task HandleWithExceptionCatchingAsync(Func<Task> action)
2464
{
2565
try
@@ -680,6 +720,15 @@ private Command BuildModuleAddCommand(Option<bool> verboseOption)
680720
{
681721
await HandleWithExceptionCatchingAsync(async () =>
682722
{
723+
// Validate module name
724+
if (!ValidateModuleName(moduleName, out var moduleNameError))
725+
{
726+
Console.ForegroundColor = ConsoleColor.Red;
727+
Console.WriteLine($"❌ {moduleNameError}");
728+
Console.ResetColor();
729+
return;
730+
}
731+
683732
// Validate db-type value
684733
var validDbTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "mssql", "mysql", "postgresql" };
685734
if (!validDbTypes.Contains(dbType))
@@ -747,7 +796,7 @@ await HandleWithExceptionCatchingAsync(async () =>
747796

748797
private Command BuildModuleRemoveCommand(Option<bool> verboseOption)
749798
{
750-
var command = new Command("remove", "Remove module from project");
799+
var command = new Command("remove", "Remove module from project. ⚠️ Warning: Once deleted, your data cannot be recovered.");
751800
var projectOption = new Option<string?>("--project");
752801
var emailOption = new Option<string?>("--email");
753802
var secretOption = new Option<string?>("--secret-code");
@@ -762,8 +811,35 @@ private Command BuildModuleRemoveCommand(Option<bool> verboseOption)
762811
{
763812
await HandleWithExceptionCatchingAsync(async () =>
764813
{
814+
// Validate module name
815+
if (!ValidateModuleName(moduleName, out var moduleNameError))
816+
{
817+
Console.ForegroundColor = ConsoleColor.Red;
818+
Console.WriteLine($"❌ {moduleNameError}");
819+
Console.ResetColor();
820+
return;
821+
}
822+
765823
var config = _configService.Load();
766824
var (name, resolvedEmail, resolvedSecret) = _configService.ResolveProjectCredentials(config, projectName, email, secret);
825+
826+
// Show warning and ask for confirmation
827+
Console.ForegroundColor = ConsoleColor.Yellow;
828+
Console.WriteLine("⚠️ WARNING: You are about to delete a module.");
829+
Console.WriteLine(" Once deleted, your data cannot be recovered.");
830+
Console.ResetColor();
831+
Console.WriteLine();
832+
Console.Write($"Are you sure you want to delete module '{moduleName}' from project '{name}'? (yes/no): ");
833+
834+
var confirmation = Console.ReadLine()?.Trim().ToLowerInvariant();
835+
836+
if (confirmation != "yes" && confirmation != "y")
837+
{
838+
Console.WriteLine("❌ Module removal cancelled.");
839+
return;
840+
}
841+
842+
Console.WriteLine();
767843
using var client = new QuickCodeApiClient(config.ApiUrl, verbose);
768844
var result = await client.RemoveProjectModuleAsync(name, resolvedEmail, resolvedSecret, moduleName);
769845
Console.WriteLine(result ? "✅ Module removed." : "⚠️ Module removal failed.");

0 commit comments

Comments
 (0)