diff --git a/internal/core/concurrency/concurrency.go b/internal/core/concurrency/concurrency.go index 839140d..551ca40 100644 --- a/internal/core/concurrency/concurrency.go +++ b/internal/core/concurrency/concurrency.go @@ -13,12 +13,29 @@ type Task struct { fn TaskFunc } -// NewTask creates a new Task. +// TaskFunc defines the type for the task function that returns a result and an error. +// @callback TaskFunc +// @param {context.Context} ctx - The context for the task, used for cancellation and deadlines. +// @returns {interface{}, error} The result of the task and an error, if any. +// +// Example: +// +// taskFunc := func(ctx context.Context) (interface{}, error) { +// return "task result", nil +// } func NewTask(fn TaskFunc) *Task { return &Task{fn: fn} } // Execute runs the task function and returns the result or an error. +// Example: +// +// result, err := task.Execute(context.Background()) +// if err != nil { +// log.Fatal(err) +// } +// +// fmt.Println(result) func (t *Task) Execute(ctx context.Context) (interface{}, error) { return t.fn(ctx) } @@ -28,7 +45,7 @@ type ExecutionMode int const ( Parallel ExecutionMode = 0 - Sequential ExecutionMode = 1 + Sequential ExecutionMode = 1 ) // TaskManager manages and executes tasks concurrently or sequentially. diff --git a/internal/core/config/config.go b/internal/core/config/config.go index 87d01a1..a542502 100644 --- a/internal/core/config/config.go +++ b/internal/core/config/config.go @@ -1,3 +1,20 @@ +/* +Package config provides functionality to load and manage application configuration +from environment variables and .env files. + +The package leverages the `godotenv` package to load environment variables from a `.env` file into +the application, allowing easy configuration management. + +Usage: + + import "your/package/path/config" + + func main() { + cfg := config.LoadConfig() + port := cfg.Get("PORT", "8080") + // Use the `port` variable... + } +*/ package config import ( @@ -8,8 +25,16 @@ import ( "github.com/joho/godotenv" ) +// Config represents a map of configuration key-value pairs loaded from the environment. type Config map[string]string +// LoadConfig loads environment variables into a Config map. It first attempts to load a `.env` file +// using the `godotenv` package. If no `.env` file is found, it logs a message but continues to load +// environment variables from the system. +// Example: +// +// cfg := config.LoadConfig() +// fmt.Println(cfg["PORT"]) func LoadConfig() Config { if err := godotenv.Load(); err != nil { log.Printf("No .env file found: %v", err) @@ -27,6 +52,14 @@ func LoadConfig() Config { return config } +// Get retrieves a value from the Config map based on the provided key. If the key does not exist +// in the Config, the function returns the specified default value. +// +// Example: +// +// cfg := config.LoadConfig() +// port := cfg.Get("PORT", "8080") +// fmt.Println("Server will run on port:", port) func (c Config) Get(key, defaultValue string) string { if value, exists := c[key]; exists { return value diff --git a/internal/core/controller/controller.go b/internal/core/controller/controller.go index 2c4d587..96cb3dd 100644 --- a/internal/core/controller/controller.go +++ b/internal/core/controller/controller.go @@ -1,16 +1,52 @@ +/* +Package controller provides a base structure and interface for defining and registering routes in the application. + +This package defines the Controller interface that all controllers must implement to register their routes, +as well as a BaseController struct that provides a default implementation of the interface. +*/ package controller import ( "github.com/hokamsingh/lessgo/internal/core/router" ) -// BASE +// Controller defines the interface that all controllers in the application must implement. +// Any controller that implements this interface must define the RegisterRoutes method, +// which is responsible for setting up the necessary routes for the controller. type Controller interface { RegisterRoutes(r *router.Router) } +// BaseController provides a default implementation of the Controller interface. +// It can be embedded in other controllers to inherit its default behavior, +// or overridden with custom implementations. type BaseController struct{} +// RegisterRoutes is the default implementation of the Controller interface's method. +// This method can be overridden by embedding BaseController in another struct +// and defining a custom implementation. +// +// Example +// +// type TestController struct { +// LessGo.BaseController +// Path string +// Service TestService +// } +// +// func NewTestController(service *TestService, path string) *TestController { +// return &TestController{ +// Service: *service, +// Path: path, +// } +// } +// +// func (tc *TestController) RegisterRoutes(r *LessGo.Router) { +// tr := r.SubRouter(tc.Path) +// tr.Get("/ping", func(ctx *LessGo.Context) { +// ctx.Send("pong") +// }) +// } func (bc *BaseController) RegisterRoutes(r *router.Router) { } diff --git a/internal/core/di/di.go b/internal/core/di/di.go index 2dc94fb..07d0b15 100644 --- a/internal/core/di/di.go +++ b/internal/core/di/di.go @@ -1,3 +1,49 @@ +/* +Package di provides a simple Dependency Injection (DI) container using the `dig` library. + +This package defines a `Container` struct that wraps the `dig.Container` and provides methods for registering and invoking dependencies. It also includes specialized methods for registering and invoking a scheduler within the DI container. + +Usage: + + import ( + "log" + + "github.com/hokamsingh/lessgo/pkg/lessgo/di" + "github.com/hokamsingh/lessgo/pkg/lessgo/scheduler" + ) + + func main() { + // Create a new DI container + container := di.NewContainer() + + // Register dependencies + if err := container.RegisterScheduler(); err != nil { + log.Fatalf("Error registering scheduler: %v", err) + } + + // Invoke a function with the scheduler dependency + err := container.InvokeScheduler(func(sched scheduler.Scheduler) error { + // Add a job to the scheduler + if err := sched.AddJob("@every 1m", func() { + log.Println("Job running every minute") + }); err != nil { + return err + } + + // Start the scheduler + sched.Start() + + // Stop the scheduler when the application shuts down + defer sched.Stop() + return nil + }) + if err != nil { + log.Fatalf("Error invoking scheduler: %v", err) + } + + // Start your application logic here + } +*/ package di import ( @@ -7,80 +53,60 @@ import ( "go.uber.org/dig" ) +// Container wraps the `dig.Container` and provides methods for registering and invoking dependencies. +// This struct serves as the main entry point for setting up and managing dependency injection within the application. type Container struct { container *dig.Container } +// NewContainer creates a new instance of `Container`. +// This method initializes the underlying `dig.Container`. +// +// Example: +// +// container := di.NewContainer() func NewContainer() *Container { return &Container{ container: dig.New(), } } +// Register adds a constructor or provider to the DI container. +// This method allows you to register dependencies that can later be resolved and injected where needed. +// +// Example: +// +// container := di.NewContainer() +// err := container.Register(func() MyService { +// return NewMyService() +// }) func (c *Container) Register(constructor interface{}) error { return c.container.Provide(constructor) } -// // Provide is an alias for Register. It registers a constructor or provider in the container -// func (c *Container) Provide(constructor interface{}) error { -// return c.Register(constructor) -// } - +// Invoke resolves dependencies and invokes the specified function. +// This method allows you to execute a function with its dependencies automatically injected by the container. +// +// Example: +// +// container := di.NewContainer() +// err := container.Invoke(func(svc MyService) { +// svc.DoSomething() +// }) func (c *Container) Invoke(function interface{}) error { return c.container.Invoke(function) } -/* -RegisterScheduler sets up and registers the scheduler in the DI container. - -This method ensures that the scheduler is available for dependency injection within your LessGo application. It uses the `cron` package under the hood to provide scheduling capabilities. - -### Example Usage - -```go -package main - -import ( - - "log" - - "github.com/hokamsingh/lessgo/pkg/lessgo" - "github.com/hokamsingh/lessgo/pkg/lessgo/scheduler" - -) - - func main() { - // Create a new DI container - container := lessgo.NewContainer() - - // Register the scheduler in the container - if err := container.RegisterScheduler(); err != nil { - log.Fatalf("Error registering scheduler: %v", err) - } - - // Use the scheduler - err := container.InvokeScheduler(func(sched scheduler.Scheduler) error { - // Add a job to the scheduler - if err := sched.AddJob("@every 1m", func() { - log.Println("Job running every minute") - }); err != nil { - return err - } - - // Start the scheduler - sched.Start() - - // Optionally, stop the scheduler when your application shuts down - defer sched.Stop() - return nil - }) - if err != nil { - log.Fatalf("Error invoking scheduler: %v", err) - } - - // Start your application logic here - } -*/ +// RegisterScheduler sets up and registers the scheduler in the DI container. +// This method ensures that the scheduler is available for dependency injection within your LessGo application. +// +// Example: +// +// container := di.NewContainer() +// err := container.RegisterScheduler() +// if err != nil { +// log.Fatalf("Error registering scheduler: %v", err) +// } func (c *Container) RegisterScheduler() error { sched := scheduler.NewCronScheduler() return c.Register(func() scheduler.Scheduler { @@ -88,7 +114,27 @@ func (c *Container) RegisterScheduler() error { }) } -// InvokeScheduler provides access to the scheduler for initialization or configuration +// InvokeScheduler provides access to the scheduler for initialization or configuration. +// This method invokes a function that takes the scheduler as a parameter, allowing you to configure it. +// +// Example: +// +// container := di.NewContainer() +// err := container.RegisterScheduler() +// if err != nil { +// log.Fatalf("Error registering scheduler: %v", err) +// } +// +// err = container.InvokeScheduler(func(sched scheduler.Scheduler) error { +// // Configure the scheduler +// return sched.AddJob("@hourly", func() { +// log.Println("Job running every hour") +// }) +// }) +// +// if err != nil { +// log.Fatalf("Error invoking scheduler: %v", err) +// } func (c *Container) InvokeScheduler(fn func(scheduler.Scheduler) error) error { return c.container.Invoke(func(sched scheduler.Scheduler) { if err := fn(sched); err != nil { diff --git a/internal/core/job/scheduler.go b/internal/core/job/scheduler.go index 107013a..8118615 100644 --- a/internal/core/job/scheduler.go +++ b/internal/core/job/scheduler.go @@ -1,25 +1,88 @@ +/* +Package scheduler provides an interface and implementation for scheduling recurring jobs using a cron-like syntax. + +This package defines a Scheduler interface and provides a CronScheduler implementation that leverages the `robfig/cron/v3` package. + +Usage: + + import "your/package/path/scheduler" + + func main() { + s := scheduler.NewCronScheduler() + + // Add a job to print "Hello, World!" every minute + err := s.AddJob("* * * * *", func() { + fmt.Println("Hello, World!") + }) + + if err != nil { + log.Fatalf("Failed to add job: %v", err) + } + + // Start the scheduler + s.Start() + + // Stop the scheduler after some time (e.g., 10 minutes) + time.Sleep(10 * time.Minute) + s.Stop() + } +*/ package scheduler import ( "github.com/robfig/cron/v3" ) +// Scheduler defines the interface for scheduling jobs. +// Implementations of this interface should provide methods to add jobs, start the scheduler, and stop it. type Scheduler interface { AddJob(schedule string, job func()) error Start() Stop() } +// CronScheduler is an implementation of the Scheduler interface using the `robfig/cron/v3` package. +// This scheduler allows for scheduling jobs based on cron expressions. type CronScheduler struct { cron *cron.Cron } +// NewCronScheduler creates a new instance of CronScheduler. +// This scheduler can be used to schedule jobs with cron expressions. +// +// Example: +// +// s := scheduler.NewCronScheduler() +// err := s.AddJob("* * * * *", func() { +// fmt.Println("Hello, World!") +// }) +// +// if err != nil { +// log.Fatalf("Failed to add job: %v", err) +// } +// +// s.Start() +// time.Sleep(10 * time.Minute) +// s.Stop() func NewCronScheduler() *CronScheduler { return &CronScheduler{ cron: cron.New(), } } +// AddJob adds a job to the scheduler with a specified cron schedule. +// The job will be executed according to the cron expression provided. +// +// Example: +// +// s := scheduler.NewCronScheduler() +// err := s.AddJob("0 0 * * *", func() { +// fmt.Println("It's midnight!") +// }) +// +// if err != nil { +// log.Fatalf("Failed to add job: %v", err) +// } func (s *CronScheduler) AddJob(schedule string, job func()) error { _, err := s.cron.AddFunc(schedule, job) if err != nil { @@ -28,10 +91,29 @@ func (s *CronScheduler) AddJob(schedule string, job func()) error { return nil } +// Start begins the execution of scheduled jobs. +// This method should be called to start the scheduler after all jobs have been added. +// +// Example: +// +// s := scheduler.NewCronScheduler() +// _ = s.AddJob("* * * * *", func() { +// fmt.Println("Running every minute") +// }) +// s.Start() func (s *CronScheduler) Start() { s.cron.Start() } +// Stop halts the execution of scheduled jobs. +// This method can be called to stop the scheduler, preventing any further job executions. +// +// Example: +// +// s := scheduler.NewCronScheduler() +// s.Start() +// time.Sleep(1 * time.Hour) +// s.Stop() func (s *CronScheduler) Stop() { s.cron.Stop() } diff --git a/internal/core/middleware/middleware.go b/internal/core/middleware/middleware.go index e6d7a94..441761d 100644 --- a/internal/core/middleware/middleware.go +++ b/internal/core/middleware/middleware.go @@ -1,16 +1,57 @@ +/* +Package middleware provides a simple interface and base implementation for creating HTTP middlewares. + +This package defines a `Middleware` interface with a `Handle` method that allows chaining HTTP handlers. It also includes a `BaseMiddleware` struct that provides a basic implementation of the middleware pattern. + +Usage: + + import ( + "net/http" + "github.com/hokamsingh/lessgo/pkg/lessgo/middleware" + ) + + func main() { + mw := &middleware.BaseMiddleware{} + + mux := http.NewServeMux() + mux.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte("Hello, World!")) + }))) + + http.ListenAndServe(":8080", mux) + } +*/ package middleware import "net/http" +// Middleware defines the interface for HTTP middlewares. +// Implementers should provide a `Handle` method that takes an `http.Handler` and returns a new `http.Handler`. +// This allows for wrapping existing handlers with additional functionality. type Middleware interface { Handle(next http.Handler) http.Handler } +// BaseMiddleware provides a basic implementation of the Middleware interface. +// It allows chaining of HTTP handlers by passing the request to the next handler in the chain. +// +// Example: +// +// mw := &middleware.BaseMiddleware{} +// http.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// w.Write([]byte("Hello, World!")) +// }))) +// +// http.ListenAndServe(":8080", nil) type BaseMiddleware struct{} -func (bm *BaseMiddleware) Handle(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // logic goes here - next.ServeHTTP(w, r) - }) -} +// Handle is the method that wraps an existing `http.Handler` with additional functionality. +// This method calls the next handler in the chain after executing any custom logic. +// +// Example: +// +// mw := &middleware.BaseMiddleware{} +// +// http.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// log.Println("Request received") +// w.W diff --git a/internal/core/module/module.go b/internal/core/module/module.go index 9175697..0d0a034 100644 --- a/internal/core/module/module.go +++ b/internal/core/module/module.go @@ -1,11 +1,44 @@ +/* +Package module provides the definition of modules, which can encapsulate controllers and services in an application. + +This package defines the `IModule` interface and a `Module` struct that allows for organizing and managing controllers, services, and submodules. It provides methods to retrieve the name, controllers, and services associated with a module. + +Usage: + + import ( + "github.com/hokamsingh/lessgo/pkg/lessgo/module" + ) + + func main() { + ctrl1 := &MyController{} + svc1 := &MyService{} + + mod := module.NewModule( + "MyModule", + []interface{}{ctrl1}, + []interface{}{svc1}, + nil, + ) + + fmt.Println(mod.GetName()) // Outputs: MyModule + fmt.Println(mod.GetControllers()) // Outputs: [] + fmt.Println(mod.GetServices()) // Outputs: [] + } +*/ package module +// IModule defines the interface for a module in the application. +// Modules are responsible for managing controllers and services and can include other submodules. +// Implementers of this interface must provide methods to get the module's name, controllers, and services. type IModule interface { GetName() string GetControllers() []interface{} GetServices() []interface{} } +// Module represents a module in the application. +// It holds the name, a list of controllers, services, and any submodules. +// The module can be used to organize and group related functionality. type Module struct { Name string submodules []IModule @@ -13,6 +46,23 @@ type Module struct { Services []interface{} } +// NewModule creates a new instance of `Module` with the specified name, controllers, services, and submodules. +// +// Example: +// +// ctrl1 := &MyController{} +// svc1 := &MyService{} +// +// mod := module.NewModule( +// "MyModule", +// []interface{}{ctrl1}, +// []interface{}{svc1}, +// nil, +// ) +// +// fmt.Println(mod.GetName()) // Outputs: MyModule +// fmt.Println(mod.GetControllers()) // Outputs: [] +// fmt.Println(mod.GetServices()) // Outputs: [] func NewModule(name string, controllers []interface{}, services []interface{}, submodules []IModule) *Module { return &Module{ Name: name, @@ -22,14 +72,34 @@ func NewModule(name string, controllers []interface{}, services []interface{}, s } } +// GetName returns the name of the module. +// +// Example: +// +// mod := module.NewModule("MyModule", nil, nil, nil) +// fmt.Println(mod.GetName()) // Outputs: MyModule func (m *Module) GetName() string { return m.Name } +// GetControllers returns a list of controllers associated with the module. +// +// Example: +// +// ctrl1 := &MyController{} +// mod := module.NewModule("MyModule", []interface{}{ctrl1}, nil, nil) +// fmt.Println(mod.GetControllers()) // Outputs: [] func (m *Module) GetControllers() []interface{} { return m.Controllers } +// GetServices returns a list of services associated with the module. +// +// Example: +// +// svc1 := &MyService{} +// mod := module.NewModule("MyModule", nil, []interface{}{svc1}, nil) +// fmt.Println(mod.GetServices()) // Outputs: [] func (m *Module) GetServices() []interface{} { return m.Services } diff --git a/internal/core/service/service.go b/internal/core/service/service.go index d45a2b2..cb9d645 100644 --- a/internal/core/service/service.go +++ b/internal/core/service/service.go @@ -1,10 +1,40 @@ +/* +Package service provides a base structure and interface for defining and implementing services in the application. + +This package defines a Service interface, which can be extended to implement various services. Additionally, it provides a BaseService struct with a default method implementation. +*/ package service +// Service defines the interface for all services in the application. +// Implementations of this interface can provide specific functionalities +// required by different parts of the application. type Service interface { } +// BaseService provides a default implementation of the Service interface. +// This struct can be embedded in other service implementations to inherit +// common functionalities or to be extended with custom methods. type BaseService struct{} +// PerformTask is a method of BaseService that performs a generic task. +// This method can be overridden by services embedding BaseService to provide +// specific behavior or functionality. +// +// Example: +// +// type MyService struct { +// service.BaseService +// } +// +// func (s *MyService) PerformTask() { +// // Custom task implementation +// fmt.Println("Performing a custom task") +// } +// +// func main() { +// s := MyService{} +// s.PerformTask() // Outputs: Performing a custom task +// } func (bs *BaseService) PerformTask() { } diff --git a/pkg/lessgo/less.go b/pkg/lessgo/less.go index 5b019a5..abc32d8 100644 --- a/pkg/lessgo/less.go +++ b/pkg/lessgo/less.go @@ -18,22 +18,75 @@ import ( ) // Expose core types + +// Controller defines the interface that all controllers in the application must implement. +// Any controller that implements this interface must define the RegisterRoutes method, +// which is responsible for setting up the necessary routes for the controller. type Controller = controller.Controller + +// BaseController provides a default implementation of the Controller interface. +// It can be embedded in other controllers to inherit its default behavior, +// or overridden with custom implementations. type BaseController = controller.BaseController + +// Container wraps the `dig.Container` and provides methods for registering and invoking dependencies. +// This struct serves as the main entry point for setting up and managing dependency injection within the application. type Container = di.Container + +// Middleware defines the interface for HTTP middlewares. +// Implementers should provide a `Handle` method that takes an `http.Handler` and returns a new `http.Handler`. +// This allows for wrapping existing handlers with additional functionality. type Middleware = middleware.Middleware + +// BaseMiddleware provides a basic implementation of the Middleware interface. +// It allows chaining of HTTP handlers by passing the request to the next handler in the chain. +// +// Example: +// +// mw := &middleware.BaseMiddleware{} +// http.Handle("/", mw.Handle(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { +// w.Write([]byte("Hello, World!")) +// }))) +// +// http.ListenAndServe(":8080", nil) type BaseMiddleware = middleware.BaseMiddleware + +// Module represents a module in the application. +// It holds the name, a list of controllers, services, and any submodules. +// The module can be used to organize and group related functionality. type Module = module.Module + +// IModule defines the interface for a module in the application. +// Modules are responsible for managing controllers and services and can include other submodules. +// Implementers of this interface must provide methods to get the module's name, controllers, and services. type IModule = module.IModule + +// Router represents an HTTP router with middleware support and error handling. type Router = router.Router + +// BaseService provides a default implementation of the Service interface. +// This struct can be embedded in other service implementations to inherit +// common functionalities or to be extended with custom methods. type BaseService = service.BaseService + +// Service defines the interface for all services in the application. +// Implementations of this interface can provide specific functionalities +// required by different parts of the application. type Service = service.Service + +// CORSOptions defines the configuration for the CORS middleware type CORSOptions = middleware.CORSOptions + +// Context holds the request and response writer and provides utility methods. type Context = context.Context + type WebSocketServer = websocket.WebSocketServer // Expose middleware types and functions + +// CORSMiddleware is the middleware that handles CORS type CORSMiddleware = middleware.CORSMiddleware + type RateLimiterMiddleware = middleware.RateLimiter type FileUploadMiddleware = middleware.FileUploadMiddleware