Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions migration/migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,17 @@ func Migrate(ctx *gofr.Context) (any, error) {
return nil, errNameEmpty
}

if err := createMigrationFile(ctx, migName); err != nil {
camelCasedMigName := toCamelCase(migName)

if err := createMigrationFile(ctx, camelCasedMigName); err != nil {
return nil, fmt.Errorf("error while creating migration file, err: %w", err)
}

if err := createAllMigration(ctx); err != nil {
return nil, fmt.Errorf("error while creating all.go file, err: %w", err)
}

return fmt.Sprintf("Successfully created migration %v", migName), nil
return fmt.Sprintf("Successfully created migration %v", camelCasedMigName), nil
}

func createMigrationFile(ctx *gofr.Context, migrationName string) error {
Expand Down Expand Up @@ -182,9 +184,38 @@ func findMigrations(files []os.DirEntry) map[string]string {
if len(fileParts) < 2 || file.Name() == allFile || fileParts[len(fileParts)-1] == "test.go" {
continue
}

existingMig[fileParts[0]] = strings.TrimSuffix(strings.Join(fileParts[1:], "_"), ".go")
// convert second part (function) to camelCase, since migration files are now generated using camelCase
existingMig[fileParts[0]] = toCamelCase(strings.TrimSuffix(strings.Join(fileParts[1:], "_"), ".go"))
}

return existingMig
}

// toCamelCase converts snake_case or kebab-case to camelCase. If input has no delimiters,
// it preserves existing casing except lowercasing the first letter.
func toCamelCase(migrationName string) string {
if migrationName == "" {
return migrationName
}
// If no delimiters, assume it's already camel/Pascal case or a single word; just lowercase first rune
if !strings.Contains(migrationName, "_") && !strings.Contains(migrationName, "-") {
return strings.ToLower(migrationName[:1]) + migrationName[1:]
}

migrationName = strings.ReplaceAll(migrationName, "-", "_")
parts := strings.FieldsFunc(migrationName, func(r rune) bool { return r == '_' || r == '-' })

if len(parts) == 0 {
return ""
}

result := strings.ToLower(parts[0])

for _, part := range parts[1:] {
if part != "" {
result += strings.ToUpper(part[:1]) + strings.ToLower(part[1:])
}
}

return result
}
31 changes: 31 additions & 0 deletions migration/migration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package migration

import "testing"

func TestToCamelCase(t *testing.T) {
tests := []struct {
name string
in string
out string
}{
{name: "snake_case", in: "create_employee_table", out: "createEmployeeTable"},
{name: "kebab_case", in: "create-employee-table", out: "createEmployeeTable"},
{name: "mixed_caps_snake", in: "Create_Employee_Table", out: "createEmployeeTable"},
{name: "single_word_lower", in: "employee", out: "employee"},
{name: "single_word_upper_first", in: "Employee", out: "employee"},
{name: "no_delimiters_lower", in: "createemployeetable", out: "createemployeetable"},
{name: "no_delimiters_camel", in: "CreateEmployeeTable", out: "createEmployeeTable"},
{name: "empty", in: "", out: ""},
{name: "leading_trailing_delims", in: "_create__employee_table_", out: "createEmployeeTable"},
{name: "multiple_delims", in: "create---employee___table", out: "createEmployeeTable"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := toCamelCase(tt.in)
if got != tt.out {
t.Fatalf("toCamelCase(%q) = %q; want %q", tt.in, got, tt.out)
}
})
}
}