Add CLI support for model generation
This commit is contained in:
		
							parent
							
								
									4e34a6d21b
								
							
						
					
					
						commit
						1295b207bb
					
				
							
								
								
									
										205
									
								
								cli/generator.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								cli/generator.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,205 @@ | |||||||
|  | package cli | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | 	"time" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type FieldInfo struct { | ||||||
|  | 	Name string | ||||||
|  | 	Type string | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // GenerateModelEntity membuat GORM-ready model, entity, dan file migrasi
 | ||||||
|  | func GenerateModelEntity(modelName string, fields []FieldInfo, baseFolder string) error { | ||||||
|  | 	if modelName == "" || len(fields) == 0 { | ||||||
|  | 		return fmt.Errorf("modelName and fields must be provided") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	modelsFolder := fmt.Sprintf("%s/internal/models", baseFolder) | ||||||
|  | 	entityFolder := fmt.Sprintf("%s/internal/entity", baseFolder) | ||||||
|  | 	migrationsFolder := fmt.Sprintf("%s/internal/migrations", baseFolder) | ||||||
|  | 
 | ||||||
|  | 	if err := os.MkdirAll(modelsFolder, os.ModePerm); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := os.MkdirAll(entityFolder, os.ModePerm); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := os.MkdirAll(migrationsFolder, os.ModePerm); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Tulis model
 | ||||||
|  | 	modelFile := fmt.Sprintf("%s/%s.go", modelsFolder, strings.ToLower(modelName)) | ||||||
|  | 	if err := writeFile(modelFile, modelName, fields, true); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Tulis entity
 | ||||||
|  | 	entityFile := fmt.Sprintf("%s/%s.go", entityFolder, strings.ToLower(modelName)) | ||||||
|  | 	if err := writeFile(entityFile, modelName, fields, false); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	moduleName, err := getModuleName(baseFolder) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	if err := createMigrationFile(modelName, migrationsFolder, moduleName); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err:= updateMasterMigration(migrationsFolder, modelName);err !=nil{ | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func writeFile(filename, modelName string, fields []FieldInfo, isModel bool) error { | ||||||
|  | 	f, err := os.Create(filename) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 	defer f.Close() | ||||||
|  | 
 | ||||||
|  | 	var lines []string | ||||||
|  | 	for _, field := range fields { | ||||||
|  | 		lines = append(lines, fmt.Sprintf("\t%s %s `gorm:\"column:%s\"`", capitalize(field.Name), mapType(field.Type), field.Name)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	var content string | ||||||
|  | 	if isModel { | ||||||
|  | 		content = fmt.Sprintf(`package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"time" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type %s struct { | ||||||
|  | 	ID        uint           `+"`gorm:\"primaryKey\"`"+` | ||||||
|  | 	CreatedAt time.Time | ||||||
|  | 	UpdatedAt time.Time | ||||||
|  | 	DeletedAt gorm.DeletedAt `+"`gorm:\"index\"`"+` | ||||||
|  | %s | ||||||
|  | } | ||||||
|  | `, modelName, joinLines(lines)) | ||||||
|  | 	} else { | ||||||
|  | 		content = fmt.Sprintf(`package entity | ||||||
|  | 
 | ||||||
|  | type %s struct { | ||||||
|  | 	ID uint | ||||||
|  | %s | ||||||
|  | } | ||||||
|  | `, modelName, joinLines(lines)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	_, err = f.WriteString(content) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fmt.Println("Create file:", filename) | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func createMigrationFile(modelName, migrationsFolder, moduleName string) error { | ||||||
|  | 	timestamp := time.Now().Format("20060102_150405") | ||||||
|  | 	filename := fmt.Sprintf("%s/%s_create_%s.go", migrationsFolder, timestamp, strings.ToLower(modelName)) | ||||||
|  | 
 | ||||||
|  | 	content := fmt.Sprintf(`package migrations | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"%s/configs" | ||||||
|  | 	"%s/internal/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Up migrates table %s
 | ||||||
|  | func Up%s() { | ||||||
|  | 	configs.DB.AutoMigrate(&models.%s{}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Down rolls back table %s
 | ||||||
|  | func Down%s() { | ||||||
|  | 	configs.DB.Migrator().DropTable(&models.%s{}) | ||||||
|  | } | ||||||
|  | `, moduleName, moduleName, modelName, modelName, modelName, modelName, modelName, modelName) | ||||||
|  | 
 | ||||||
|  | 	return os.WriteFile(filename, []byte(content), 0644) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func updateMasterMigration(migrationsFolder, modelName string) error { | ||||||
|  | 	masterFile := fmt.Sprintf("%s/migrate.go", migrationsFolder) | ||||||
|  | 
 | ||||||
|  | 	// Jika belum ada, buat file baru
 | ||||||
|  | 	if _, err := os.Stat(masterFile); os.IsNotExist(err) { | ||||||
|  | 		content := `package migrations | ||||||
|  | 
 | ||||||
|  | import "fmt" | ||||||
|  | 
 | ||||||
|  | func MigrateAll() { | ||||||
|  | 	fmt.Println("Running migrations...") | ||||||
|  | 	Up` + modelName + `() | ||||||
|  | 	// Add other migrations here
 | ||||||
|  | 	fmt.Println("Migrations completed!") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RollbackAll() { | ||||||
|  | 	fmt.Println("Rolling back migrations...") | ||||||
|  | 	Down` + modelName + `() | ||||||
|  | 	// Add other rollbacks here
 | ||||||
|  | 	fmt.Println("Rollback completed!") | ||||||
|  | } | ||||||
|  | ` | ||||||
|  | 		return os.WriteFile(masterFile, []byte(content), 0644) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	// Jika sudah ada, append import Up/Down baru jika belum ada
 | ||||||
|  | 	data, err := os.ReadFile(masterFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	text := string(data) | ||||||
|  | 	if !strings.Contains(text, "Up"+modelName+"()") { | ||||||
|  | 		text = strings.Replace(text, "// Add other migrations here", "Up"+modelName+"()\n\t// Add other migrations here", 1) | ||||||
|  | 	} | ||||||
|  | 	if !strings.Contains(text, "Down"+modelName+"()") { | ||||||
|  | 		text = strings.Replace(text, "// Add other rollbacks here", "Down"+modelName+"()\n\t// Add other rollbacks here", 1) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return os.WriteFile(masterFile, []byte(text), 0644) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func mapType(t string) string { | ||||||
|  | 	switch t { | ||||||
|  | 	case "string": | ||||||
|  | 		return "string" | ||||||
|  | 	case "int": | ||||||
|  | 		return "int" | ||||||
|  | 	case "float": | ||||||
|  | 		return "float64" | ||||||
|  | 	case "bool": | ||||||
|  | 		return "bool" | ||||||
|  | 	default: | ||||||
|  | 		return "string" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func capitalize(s string) string { | ||||||
|  | 	if len(s) == 0 { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	return strings.ToUpper(s[:1]) + s[1:] | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func joinLines(lines []string) string { | ||||||
|  | 	if len(lines) == 0 { | ||||||
|  | 		return "" | ||||||
|  | 	} | ||||||
|  | 	return "\n" + strings.Join(lines, "\n") | ||||||
|  | } | ||||||
							
								
								
									
										60
									
								
								cli/generatorDbConfig.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								cli/generatorDbConfig.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | |||||||
|  | package cli | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // GenerateDBConfig membuat file configs/db.go untuk berbagai DB
 | ||||||
|  | func GenerateDBConfig(baseFolder, dbType string) error { | ||||||
|  | 	configsFolder := fmt.Sprintf("%s/configs", baseFolder) | ||||||
|  | 	if err := os.MkdirAll(configsFolder, os.ModePerm); err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	dbFile := fmt.Sprintf("%s/db.go", configsFolder) | ||||||
|  | 
 | ||||||
|  | 	dbType = strings.ToLower(dbType) | ||||||
|  | 	var importLine, openLine string | ||||||
|  | 
 | ||||||
|  | 	switch dbType { | ||||||
|  | 	case "postgres": | ||||||
|  | 		importLine = `"gorm.io/driver/postgres"` | ||||||
|  | 		openLine = `gorm.Open(postgres.Open(dsn), &gorm.Config{})` | ||||||
|  | 	case "mysql": | ||||||
|  | 		importLine = `"gorm.io/driver/mysql"` | ||||||
|  | 		openLine = `gorm.Open(mysql.Open(dsn), &gorm.Config{})` | ||||||
|  | 	case "sqlite": | ||||||
|  | 		importLine = `"gorm.io/driver/sqlite"` | ||||||
|  | 		openLine = `gorm.Open(sqlite.Open(dsn), &gorm.Config{})` | ||||||
|  | 	case "sqlserver": | ||||||
|  | 		importLine = `"gorm.io/driver/sqlserver"` | ||||||
|  | 		openLine = `gorm.Open(sqlserver.Open(dsn), &gorm.Config{})` | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("Unsupported DB type: %s", dbType) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	content := fmt.Sprintf(`package configs | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"log" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | 	%s | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var DB *gorm.DB | ||||||
|  | 
 | ||||||
|  | func InitDB(dsn string) { | ||||||
|  | 	var err error | ||||||
|  | 	DB, err = %s | ||||||
|  | 	if err != nil { | ||||||
|  | 		log.Fatalf("Failed to connect to database: %%v", err) | ||||||
|  | 	} | ||||||
|  | 	fmt.Println("Database connected via GORM") | ||||||
|  | } | ||||||
|  | `, importLine, openLine) | ||||||
|  | 
 | ||||||
|  | 	return os.WriteFile(dbFile, []byte(content), 0644) | ||||||
|  | } | ||||||
							
								
								
									
										31
									
								
								cli/getmodule.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								cli/getmodule.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | |||||||
|  | package cli | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"bufio" | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | func getModuleName(baseFolder string) (string, error) { | ||||||
|  | 	file, err := os.Open(baseFolder + "/go.mod") | ||||||
|  | 	if err != nil { | ||||||
|  | 		return "", fmt.Errorf("cannot open go.mod: %v", err) | ||||||
|  | 	} | ||||||
|  | 	defer file.Close() | ||||||
|  | 
 | ||||||
|  | 	scanner := bufio.NewScanner(file) | ||||||
|  | 	for scanner.Scan() { | ||||||
|  | 		line := strings.TrimSpace(scanner.Text()) | ||||||
|  | 		if strings.HasPrefix(line, "module ") { | ||||||
|  | 			return strings.TrimSpace(strings.TrimPrefix(line, "module ")), nil | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if err := scanner.Err(); err != nil { | ||||||
|  | 		return "", fmt.Errorf("error reading go.mod: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return "", fmt.Errorf("module name not found in go.mod") | ||||||
|  | } | ||||||
							
								
								
									
										47
									
								
								cli/relation.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								cli/relation.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | package cli | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"os" | ||||||
|  | 	"strings" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type RelationType string | ||||||
|  | 
 | ||||||
|  | const ( | ||||||
|  | 	One2Many  RelationType = "one2many" | ||||||
|  | 	Many2Many RelationType = "many2many" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type RelationInfo struct { | ||||||
|  | 	FieldName string | ||||||
|  | 	Target    string | ||||||
|  | 	Type      RelationType | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // AddRelation menambahkan relasi ke file model
 | ||||||
|  | func AddRelation(modelFile string, relations []RelationInfo, modelName string) error { | ||||||
|  | 	content, err := os.ReadFile(modelFile) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	lines := strings.Split(string(content), "\n") | ||||||
|  | 	for i, line := range lines { | ||||||
|  | 		if strings.TrimSpace(line) == "}" { | ||||||
|  | 			for _, r := range relations { | ||||||
|  | 				var relLine string | ||||||
|  | 				if r.Type == One2Many { | ||||||
|  | 					relLine = fmt.Sprintf("\t%s []%s `gorm:\"foreignKey:%sID\"`", r.FieldName, r.Target, modelName) | ||||||
|  | 				} else if r.Type == Many2Many { | ||||||
|  | 					relLine = fmt.Sprintf("\t%s []%s `gorm:\"many2many:%s_%s\"`", r.FieldName, r.Target, strings.ToLower(modelName), strings.ToLower(r.Target)) | ||||||
|  | 				} | ||||||
|  | 				lines = append(lines[:i], append([]string{relLine}, lines[i:]...)...) | ||||||
|  | 				i++ | ||||||
|  | 			} | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return os.WriteFile(modelFile, []byte(strings.Join(lines, "\n")), 0644) | ||||||
|  | } | ||||||
							
								
								
									
										77
									
								
								cmd/cli.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								cmd/cli.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | |||||||
|  | package main | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"flag" | ||||||
|  | 	"fmt" | ||||||
|  | 	"log" | ||||||
|  | 	"strings" | ||||||
|  | 
 | ||||||
|  | 	"gorm.io/gorm/cli" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | func main() { | ||||||
|  | 	// --- Flags ---
 | ||||||
|  | 	modelName := flag.String("name", "", "Model name, e.g.: User") | ||||||
|  | 	attributes := flag.String("attributes", "", "Model attributes, e.g.: name:string,email:string") | ||||||
|  | 	baseFolder := flag.String("folder", ".", "Base folder of the project") | ||||||
|  | 	relations := flag.String("relations", "", "Relations, e.g.: Products:Product:one2many,Tags:Tag:many2many") | ||||||
|  | 	initDB := flag.Bool("init", false, "Generate configs/db.go for supported databases") | ||||||
|  | 	dbType := flag.String("db", "postgres", "Database type: postgres, mysql, sqlite, sqlserver") | ||||||
|  | 
 | ||||||
|  | 	flag.Parse() | ||||||
|  | 
 | ||||||
|  | 	if *initDB { | ||||||
|  | 		if err := cli.GenerateDBConfig(*baseFolder, *dbType); err != nil { | ||||||
|  | 			log.Fatal("Failed to create db.go:", err) | ||||||
|  | 		} | ||||||
|  | 		fmt.Println("configs/db.go created successfully for", *dbType) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if *modelName == "" || *attributes == "" { | ||||||
|  | 		fmt.Println("Use : go run main.go --name User --attributes name:string,email:string") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fields := parseFields(*attributes) | ||||||
|  | 
 | ||||||
|  | 	if err := cli.GenerateModelEntity(*modelName, fields, *baseFolder); err != nil { | ||||||
|  | 		log.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if *relations != "" { | ||||||
|  | 		rels := parseRelations(*relations) | ||||||
|  | 		modelFile := fmt.Sprintf("%s/internal/models/%s.go", *baseFolder, strings.ToLower(*modelName)) | ||||||
|  | 		if err := cli.AddRelation(modelFile, rels, *modelName); err != nil { | ||||||
|  | 			log.Fatal(err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	fmt.Println("Done!") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // --- Helpers ---
 | ||||||
|  | func parseFields(attr string) []cli.FieldInfo { | ||||||
|  | 	var fields []cli.FieldInfo | ||||||
|  | 	for _, a := range strings.Split(attr, ",") { | ||||||
|  | 		parts := strings.Split(a, ":") | ||||||
|  | 		if len(parts) != 2 { | ||||||
|  | 			log.Fatalf("Attribute format is invalid: %s", a) | ||||||
|  | 		} | ||||||
|  | 		fields = append(fields, cli.FieldInfo{Name: parts[0], Type: parts[1]}) | ||||||
|  | 	} | ||||||
|  | 	return fields | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseRelations(rel string) []cli.RelationInfo { | ||||||
|  | 	var rels []cli.RelationInfo | ||||||
|  | 	for _, r := range strings.Split(rel, ",") { | ||||||
|  | 		parts := strings.Split(r, ":") | ||||||
|  | 		if len(parts) != 3 { | ||||||
|  | 			log.Fatalf("Relation format is invalid: %s", r) | ||||||
|  | 		} | ||||||
|  | 		rt := cli.RelationType(parts[2]) | ||||||
|  | 		rels = append(rels, cli.RelationInfo{FieldName: parts[0], Target: parts[1], Type: rt}) | ||||||
|  | 	} | ||||||
|  | 	return rels | ||||||
|  | } | ||||||
							
								
								
									
										8
									
								
								internal/entity/user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								internal/entity/user.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | package entity | ||||||
|  | 
 | ||||||
|  | type User struct { | ||||||
|  | 	ID uint | ||||||
|  | 
 | ||||||
|  | 	Name string `gorm:"column:name"` | ||||||
|  | 	Email string `gorm:"column:email"` | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								internal/migrations/20250821_051926_create_user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/migrations/20250821_051926_create_user.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | package migrations | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"gorm.io/gorm/configs" | ||||||
|  | 	"gorm.io/gorm/internal/models" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | // Up migrates table User
 | ||||||
|  | func UpUser() { | ||||||
|  | 	configs.DB.AutoMigrate(&models.User{}) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Down rolls back table User
 | ||||||
|  | func DownUser() { | ||||||
|  | 	configs.DB.Migrator().DropTable(&models.User{}) | ||||||
|  | } | ||||||
							
								
								
									
										17
									
								
								internal/migrations/migrate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								internal/migrations/migrate.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,17 @@ | |||||||
|  | package migrations | ||||||
|  | 
 | ||||||
|  | import "fmt" | ||||||
|  | 
 | ||||||
|  | func MigrateAll() { | ||||||
|  | 	fmt.Println("Running migrations...") | ||||||
|  | 	UpUser() | ||||||
|  | 	// Add other migrations here
 | ||||||
|  | 	fmt.Println("Migrations completed!") | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func RollbackAll() { | ||||||
|  | 	fmt.Println("Rolling back migrations...") | ||||||
|  | 	DownUser() | ||||||
|  | 	// Add other rollbacks here
 | ||||||
|  | 	fmt.Println("Rollback completed!") | ||||||
|  | } | ||||||
							
								
								
									
										16
									
								
								internal/models/user.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								internal/models/user.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | |||||||
|  | package models | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"time" | ||||||
|  | 	"gorm.io/gorm" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type User struct { | ||||||
|  | 	ID        uint           `gorm:"primaryKey"` | ||||||
|  | 	CreatedAt time.Time | ||||||
|  | 	UpdatedAt time.Time | ||||||
|  | 	DeletedAt gorm.DeletedAt `gorm:"index"` | ||||||
|  | 
 | ||||||
|  | 	Name string `gorm:"column:name"` | ||||||
|  | 	Email string `gorm:"column:email"` | ||||||
|  | } | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 M.RIZKI  I
						M.RIZKI  I