diff --git a/internal/routes/v1/routes.go b/internal/routes/v1/routes.go index 0aeed2a..37dd3a3 100644 --- a/internal/routes/v1/routes.go +++ b/internal/routes/v1/routes.go @@ -117,7 +117,7 @@ func RegisterRoutes(cfg *config.Config) *gin.Engine { Logger: *logger.Default(), Validator: validator.New(), }) - pesertaGroup := v1.Group("/Peserta") + pesertaGroup := v1.Group("/peserta") pesertaGroup.GET("/nokartu/:nokartu", pesertaHandler.GetBynokartu) pesertaGroup.GET("/nik/:nik", pesertaHandler.GetBynik) diff --git a/tools/bpjs/generate-handler.go b/tools/bpjs/generate-handler.go index b7f16c7..1b4d8c4 100644 --- a/tools/bpjs/generate-handler.go +++ b/tools/bpjs/generate-handler.go @@ -3470,125 +3470,125 @@ func generateRoutes(serviceName string, svc Service, gc GlobalConfig) error { routesContentStr := string(routesContent) - // Check if routes are already registered - if strings.Contains(routesContentStr, fmt.Sprintf("Register%sRoutes", svc.Name)) { - fmt.Printf("⚠️ Routes for %s already registered in main routes file\n", svc.Name) - return nil - } - - var imports []string + var newImports []string var allRoutes []string - // ✅ PERBAIKAN: Gunakan groupName dengan benar - // ✅ VALIDASI: Track handler folder yang sudah diimport + // Track processed folders to avoid duplicate imports processedFolders := make(map[string]bool) + for groupName, grp := range svc.Endpoints { - // Import berdasarkan handler folder - if !processedFolders[grp.HandlerFolder] { - importLine := fmt.Sprintf("\t%sHandlers \"%s/internal/handlers/%s\"", - grp.HandlerFolder, gc.ModuleName, grp.HandlerFolder) - imports = append(imports, importLine) + // Check and add import if not exists + importLine := fmt.Sprintf("%sHandlers \"%s/internal/handlers/%s\"", + grp.HandlerFolder, gc.ModuleName, grp.HandlerFolder) + if !processedFolders[grp.HandlerFolder] && !strings.Contains(routesContentStr, importLine) { + newImports = append(newImports, fmt.Sprintf("\t%s", importLine)) processedFolders[grp.HandlerFolder] = true - fmt.Printf("✅ Added import: %sHandlers\n", grp.HandlerFolder) - } else { + fmt.Printf("✅ Will add import: %sHandlers\n", grp.HandlerFolder) + } else if processedFolders[grp.HandlerFolder] { fmt.Printf("⚠️ Skipped duplicate import for folder: %s\n", grp.HandlerFolder) + } else { + fmt.Printf("⚠️ Import already exists: %sHandlers\n", grp.HandlerFolder) } var routesCode strings.Builder - // Gunakan groupName untuk comment dan identifier + // Comment for the group routesCode.WriteString(fmt.Sprintf("\n\t// %s (%s) routes\n", grp.Description, groupName)) - // Handler instantiation menggunakan HandlerName dari config - routesCode.WriteString(fmt.Sprintf("\t%sHandler := %sHandlers.New%sHandler(%sHandlers.%sHandlerConfig{\n", - strings.ToLower(grp.HandlerName), - grp.HandlerFolder, - grp.HandlerName, - grp.HandlerFolder, - grp.HandlerName)) + // Check if handler is already instantiated + handlerVar := strings.ToLower(grp.HandlerName) + "Handler" + handlerInstantiation := fmt.Sprintf("%s := %sHandlers.New%sHandler(%sHandlers.%sHandlerConfig{", + handlerVar, grp.HandlerFolder, grp.HandlerName, grp.HandlerFolder, grp.HandlerName) + if !strings.Contains(routesContentStr, handlerInstantiation) { + routesCode.WriteString(fmt.Sprintf("\t%s := %sHandlers.New%sHandler(%sHandlers.%sHandlerConfig{\n", + handlerVar, grp.HandlerFolder, grp.HandlerName, grp.HandlerFolder, grp.HandlerName)) + routesCode.WriteString("\t\tConfig: cfg,\n") + routesCode.WriteString("\t\tLogger: *logger.Default(),\n") + routesCode.WriteString("\t\tValidator: validator.New(),\n") + routesCode.WriteString("\t})\n") + fmt.Printf("✅ Will add handler instantiation: %s\n", handlerVar) + } else { + fmt.Printf("⚠️ Handler already instantiated: %s\n", handlerVar) + } - routesCode.WriteString("\t\tConfig: cfg,\n") - routesCode.WriteString("\t\tLogger: *logger.Default(),\n") - routesCode.WriteString("\t\tValidator: validator.New(),\n") - routesCode.WriteString("\t})\n") - - // ✅ GUNAKAN groupName untuk route group path - routesCode.WriteString(fmt.Sprintf("\t%sGroup := v1.Group(\"/%s\")\n", - strings.ToLower(grp.HandlerName), groupName)) // ← Gunakan groupName di sini + // Check if group is already created + groupVar := strings.ToLower(grp.HandlerName) + "Group" + groupCreation := fmt.Sprintf("%s := v1.Group(\"/%s\")", groupVar, groupName) + if !strings.Contains(routesContentStr, groupCreation) { + routesCode.WriteString(fmt.Sprintf("\t%s := v1.Group(\"/%s\")\n", groupVar, groupName)) + fmt.Printf("✅ Will add group: %s\n", groupVar) + } else { + fmt.Printf("⚠️ Group already exists: %s\n", groupVar) + } // Process functions for fname, fcfg := range grp.Functions { td := processFunctionData(svc, grp, fname, fcfg, gc) for _, endpoint := range td.Endpoints { - handlerVar := strings.ToLower(grp.HandlerName) + "Handler" - groupVar := strings.ToLower(grp.HandlerName) + "Group" - - // ✅ MODIFIKASI: Loop through methods dan gunakan specific routes + // Loop through methods and use specific routes for _, method := range fcfg.Methods { var cleanPath string - // ✅ Pilih path berdasarkan method + // Select path based on method switch strings.ToUpper(method) { case "GET": cleanPath = fcfg.GetRoutes if cleanPath == "" { - cleanPath = fcfg.GetPath // fallback ke get_path + cleanPath = fcfg.GetPath } case "POST": cleanPath = fcfg.PostRoutes if cleanPath == "" { - cleanPath = fcfg.PostPath // fallback ke post_path + cleanPath = fcfg.PostPath } case "PUT": cleanPath = fcfg.PutRoutes if cleanPath == "" { - cleanPath = fcfg.PutPath // fallback ke put_path + cleanPath = fcfg.PutPath } case "DELETE": cleanPath = fcfg.DeleteRoutes if cleanPath == "" { - cleanPath = fcfg.DeletePath // fallback ke delete_path + cleanPath = fcfg.DeletePath } default: fmt.Printf("⚠️ Unsupported HTTP method: %s for function %s\n", method, fname) continue } - // ✅ Final fallback ke path jika specific route kosong + // Final fallback to path if specific route empty if cleanPath == "" { cleanPath = fcfg.Path } - // ✅ Bersihkan path - hapus prefix groupName jika ada + // Clean path - remove prefix groupName if present and ensure lowercase if strings.HasPrefix(cleanPath, "/"+groupName) { cleanPath = strings.TrimPrefix(cleanPath, "/"+groupName) } if cleanPath == "" { cleanPath = "/" } + // Ensure path is lowercase for consistency + cleanPath = strings.ToLower(cleanPath) - // ✅ Generate route berdasarkan method + // Generate route based on method var routeLine string switch strings.ToUpper(method) { case "GET": - routeLine = fmt.Sprintf("%s.GET(\"%s\", %s.Get%s)\n", - groupVar, cleanPath, handlerVar, endpoint.Name) + routeLine = fmt.Sprintf("\t%s.GET(\"%s\", %s.Get%s)", groupVar, cleanPath, handlerVar, endpoint.Name) case "POST": - routeLine = fmt.Sprintf("%s.POST(\"%s\", %s.Create%s)\n", - groupVar, cleanPath, handlerVar, endpoint.Name) + routeLine = fmt.Sprintf("\t%s.POST(\"%s\", %s.Create%s)", groupVar, cleanPath, handlerVar, endpoint.Name) case "PUT": - routeLine = fmt.Sprintf("%s.PUT(\"%s\", %s.Update%s)\n", - groupVar, cleanPath, handlerVar, endpoint.Name) + routeLine = fmt.Sprintf("\t%s.PUT(\"%s\", %s.Update%s)", groupVar, cleanPath, handlerVar, endpoint.Name) case "DELETE": - routeLine = fmt.Sprintf("%s.DELETE(\"%s\", %s.Delete%s)\n", - groupVar, cleanPath, handlerVar, endpoint.Name) + routeLine = fmt.Sprintf("\t%s.DELETE(\"%s\", %s.Delete%s)", groupVar, cleanPath, handlerVar, endpoint.Name) } - // ✅ PERBAIKAN: Check if route already exists - if !strings.Contains(routesContentStr, strings.TrimSpace(routeLine)) { - routesCode.WriteString(routeLine) - fmt.Printf("✅ Added route: %s %s\n", method, cleanPath) + // Check if route already exists + if !strings.Contains(routesContentStr, routeLine) { + routesCode.WriteString(routeLine + "\n") + fmt.Printf("✅ Will add route: %s %s\n", method, cleanPath) } else { fmt.Printf("⚠️ Skipped duplicate route: %s %s\n", method, cleanPath) } @@ -3596,81 +3596,55 @@ func generateRoutes(serviceName string, svc Service, gc GlobalConfig) error { } } - allRoutes = append(allRoutes, routesCode.String()) + if routesCode.Len() > 0 { + allRoutes = append(allRoutes, routesCode.String()) + } } - // ✅ PERBAIKAN: Insert imports setelah "api-service/internal/database" - if len(imports) > 0 { - // ✅ PERBAIKAN: Hilangkan newline di awal, langsung import lines saja - importSection := strings.Join(imports, "\n") + "\n" + // Insert new imports if any + if len(newImports) > 0 { + importSection := strings.Join(newImports, "\n") + "\n" - // ✅ PERBAIKAN: Cari posisi setelah "api-service/internal/database" + // Find the database import marker databaseImportMarker := fmt.Sprintf("\"%s/internal/database\"", gc.ModuleName) - if strings.Contains(routesContentStr, databaseImportMarker) { - // Temukan posisi marker - markerPos := strings.Index(routesContentStr, databaseImportMarker) - // Temukan akhir baris dari marker - endOfLinePos := strings.Index(routesContentStr[markerPos:], "\n") + markerPos - // Insert import section setelah baris marker - routesContentStr = routesContentStr[:endOfLinePos+1] + importSection + routesContentStr[endOfLinePos+1:] - fmt.Printf("✅ Inserted imports after database import\n") + if idx := strings.Index(routesContentStr, databaseImportMarker); idx != -1 { + // Find end of that line + endOfLine := strings.Index(routesContentStr[idx:], "\n") + idx + 1 + routesContentStr = routesContentStr[:endOfLine] + importSection + routesContentStr[endOfLine:] + fmt.Printf("✅ Inserted new imports after database import\n") } else { - // Fallback: Insert setelah "import (" jika marker tidak ditemukan - importMarker := "import (" - if strings.Contains(routesContentStr, importMarker) { - importIndex := strings.Index(routesContentStr, importMarker) + len(importMarker) - routesContentStr = routesContentStr[:importIndex] + "\n" + importSection + routesContentStr[importIndex:] + // Fallback to after import ( + if idx := strings.Index(routesContentStr, "import ("); idx != -1 { + importStart := idx + len("import (") + routesContentStr = routesContentStr[:importStart] + "\n" + importSection + routesContentStr[importStart:] fmt.Printf("⚠️ Database import not found, inserted after import (\n") - } else { - fmt.Printf("⚠️ Could not find import section to insert imports\n") } } } - // ✅ PERBAIKAN: Try new format first, then fallback to old format - var publishedRoutesMarker string + // Find insertion point for routes var insertionPoint int - - // Try the new multi-line format first newFormatMarker := "// =============================================================================\n// PUBLISHED ROUTES\n// =============================================================================" - if strings.Contains(routesContentStr, newFormatMarker) { - publishedRoutesMarker = newFormatMarker + if idx := strings.Index(routesContentStr, newFormatMarker); idx != -1 { + insertionPoint = idx + len(newFormatMarker) fmt.Printf("✅ Found new format PUBLISHED ROUTES marker\n") + } else if idx := strings.Index(routesContentStr, "// PUBLISHED ROUTES"); idx != -1 { + insertionPoint = idx + len("// PUBLISHED ROUTES") + fmt.Printf("⚠️ Found old format PUBLISHED ROUTES marker\n") } else { - // Fallback to old single-line format - oldFormatMarker := "// PUBLISHED ROUTES" - if strings.Contains(routesContentStr, oldFormatMarker) { - publishedRoutesMarker = oldFormatMarker - fmt.Printf("⚠️ Found old format PUBLISHED ROUTES marker, using fallback\n") - } else { - return fmt.Errorf("PUBLISHED ROUTES marker not found in routes.go (tried both new and old formats)") - } + return fmt.Errorf("PUBLISHED ROUTES marker not found in routes.go") } - insertionPoint = strings.Index(routesContentStr, publishedRoutesMarker) + len(publishedRoutesMarker) - - // If we want to upgrade to the new format, we can replace the old marker with the new one - if publishedRoutesMarker == "// PUBLISHED ROUTES" { - // Replace old marker with new format - newRoutesContent := routesContentStr[:insertionPoint] + "\n" + strings.Join(allRoutes, "\n") + "\n" + routesContentStr[insertionPoint:] - - // Now replace the old marker with the new format - newRoutesContent = strings.Replace(newRoutesContent, "// PUBLISHED ROUTES", newFormatMarker, 1) - + // Insert new routes + if len(allRoutes) > 0 { + newRoutesContent := routesContentStr[:insertionPoint] + "\n" + strings.Join(allRoutes, "\n") + routesContentStr[insertionPoint:] err = ioutil.WriteFile(routesFilePath, []byte(newRoutesContent), 0644) if err != nil { return fmt.Errorf("failed to write updated routes file: %w", err) } - fmt.Printf("✅ Updated main routes file with %s routes and upgraded marker format\n", svc.Name) + fmt.Printf("✅ Updated main routes file with new routes for %s\n", svc.Name) } else { - // Use existing new format - newRoutesContent := routesContentStr[:insertionPoint] + "\n" + strings.Join(allRoutes, "\n") + "\n" + routesContentStr[insertionPoint:] - - err = ioutil.WriteFile(routesFilePath, []byte(newRoutesContent), 0644) - if err != nil { - return fmt.Errorf("failed to write updated routes file: %w", err) - } - fmt.Printf("✅ Updated main routes file with %s routes\n", svc.Name) + fmt.Printf("⏭️ No new routes to add for %s\n", svc.Name) } return nil