core

package module
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 6, 2026 License: MIT Imports: 13 Imported by: 2

README

GoNest Core Module

The core module provides the fundamental architecture for building NestJS-style applications in Go.

Features

  • Module System: Organize your application into modules
  • Dependency Injection: Automatic dependency resolution
  • Lifecycle Hooks: Control initialization and shutdown
  • Request Context: Type-safe request handling
  • Routing: Simple and intuitive route registration
  • Metadata Storage: Attach metadata to types

Installation

go get github.com/gonest-dev/gonest

Quick Start

1. Create a Module
package main

import "github.com/gonest-dev/gonest/core"

type AppModule struct{}

func (m *AppModule) Configure(b *core.ModuleBuilder) {
  b.Controllers(&AppController{}).
    Providers(&AppService{})
}
2. Create a Service
type AppService struct{}

func (s *AppService) GetHello() string {
  return "Hello from GoNest!"
}

// Lifecycle hook (optional)
func (s *AppService) OnModuleInit(ctx context.Context) error {
  log.Println("Service initialized")
  return nil
}
3. Create a Controller
type AppController struct {
  appService *AppService
}

func (c *AppController) Routes() []core.RouteDefinition {
  return []core.RouteDefinition{
    { Method:  "GET", Path:  "/", Handler: c.GetHello },
    { Method:  "GET", Path:  "/user/:id", Handler: c.GetUser },
    { Method:  "POST", Path:  "/user", Handler: c.CreateUser },
  }
}

func (c *AppController) GetHello(ctx *core.Context) error {
  message := c.appService.GetHello()
  return ctx.JSON(200, map[string]string{"message": message})
}

func (c *AppController) GetUser(ctx *core.Context) error {
  id := ctx.Param("id")
  return ctx.JSON(200, map[string]string{"id": id, "name": "User " + id})
}

func (c *AppController) CreateUser(ctx *core.Context) error {
  var dto CreateUserDto
  if err := ctx.BindJSON(&dto); err != nil {
    return ctx.JSON(400, map[string]string{"error": "Invalid body"})
  }
  
  return ctx.JSON(201, dto)
}
4. Bootstrap Application
func main() {
  app := core.NestFactory{}.Create(&AppModule{})
  
  if err := app.Listen(":3000"); err != nil {
    log.Fatal(err)
  }
}

Module System

Basic Module
type UserModule struct{}

func (m *UserModule) Configure(b *core.ModuleBuilder) {
  b.Controllers(&UserController{}).
    Providers(&UserService{}, &UserRepository{})
}
Module with Imports
type AppModule struct{}

func (m *AppModule) Configure(b *core.ModuleBuilder) {
  b.Imports(&UserModule{}, &AuthModule{}).
    Controllers(&AppController{}).
    Providers(&AppService{})
}
Module with Exports
type SharedModule struct{}

func (m *SharedModule) Configure(b *core.ModuleBuilder) {
  b.Providers(&SharedService{}).
    Exports(&SharedService{})  // Make available to importing modules
}

Lifecycle Hooks

OnModuleInit

Called when the module is initialized, after dependencies are resolved.

func (s *DatabaseService) OnModuleInit(ctx context.Context) error {
  return s.Connect()
}
OnApplicationBootstrap

Called after all modules are initialized.

func (s *CacheService) OnApplicationBootstrap(ctx context.Context) error {
  return s.WarmupCache()
}
OnModuleDestroy

Called when the module is being destroyed.

func (s *DatabaseService) OnModuleDestroy(ctx context.Context) error {
  return s.Disconnect()
}
OnApplicationShutdown

Called before the application shuts down.

func (s *QueueService) OnApplicationShutdown(ctx context.Context) error {
  return s.FlushQueue()
}

Request Context

The Context provides a unified interface for handling HTTP requests:

Reading Request Data
func (c *Controller) Handler(ctx *core.Context) error {
  // Path parameters
  id := ctx.Param("id")
  
  // Query parameters
  page := ctx.Query("page")
  limit := ctx.QueryDefault("limit", "10")
  
  // Headers
  auth := ctx.Header("Authorization")
  
  // JSON body
  var dto CreateDto
  if err := ctx.BindJSON(&dto); err != nil {
    return err
  }
  
  // Raw body
  body, err := ctx.Body()
}
Sending Responses
// JSON response
ctx.JSON(200, map[string]string{"status": "ok"})

// String response
ctx.String(200, "Hello, World!")

// HTML response
ctx.HTML(200, "<h1>Hello</h1>")

// Raw data
ctx.Data(200, "application/pdf", pdfBytes)

// Status only
ctx.Status(204)
Context Metadata
// Store data
ctx.Set("user", user)
ctx.Set("requestId", uuid.New())

// Retrieve data
user := ctx.Get("user")
userId := ctx.GetString("userId")
isAdmin := ctx.GetBool("isAdmin")
count := ctx.GetInt("count")

Routing

Basic Routes
func (c *Controller) Routes() []core.RouteDefinition {
  return []core.RouteDefinition{
    {Method: "GET", Path: "/users", Handler: c.GetUsers},
    {Method: "POST", Path: "/users", Handler: c.CreateUser},
    {Method: "GET", Path: "/users/:id", Handler: c.GetUser},
    {Method: "PUT", Path: "/users/:id", Handler: c.UpdateUser},
    {Method: "DELETE", Path: "/users/:id", Handler: c.DeleteUser},
  }
}
Path Parameters
// Route: /users/:id/posts/:postId
func (c *Controller) GetUserPost(ctx *core.Context) error {
  userId := ctx.Param("id")
  postId := ctx.Param("postId")
  // ...
}
Middleware
func LoggingMiddleware(next core.HandlerFunc) core.HandlerFunc {
  return func(ctx *core.Context) error {
    start := time.Now()
    err := next(ctx)
    log.Printf("%s %s - %v", ctx.Method(), ctx.Path(), time.Since(start))
    return err
  }
}

// Apply to route
{
  Method: "GET",
  Path: "/protected",
  Handler: c.Protected,
  Middlewares: []core.MiddlewareFunc{LoggingMiddleware, AuthMiddleware},
}

Application Options

app := core.NestFactory{}.Create(
  &AppModule{},
  core.WithShutdownTimeout(30 * time.Second),
  core.WithReadTimeout(10 * time.Second),
  core.WithWriteTimeout(10 * time.Second),
  core.WithIdleTimeout(120 * time.Second),
)

Graceful Shutdown

The application handles graceful shutdown automatically:

app.Listen(":3000")  // Blocks until SIGINT or SIGTERM

// On shutdown:
// 1. Calls OnApplicationShutdown hooks
// 2. Calls OnModuleDestroy hooks
// 3. Stops HTTP server gracefully

Error Handling

func (c *Controller) Handler(ctx *core.Context) error {
  if err := doSomething(); err != nil {
    return ctx.JSON(500, map[string]string{
      "error": err.Error(),
    })
  }
  return ctx.JSON(200, result)
}

Testing

func TestController(t *testing.T) {
  // Create test context
  req := httptest.NewRequest("GET", "/test", nil)
  w := httptest.NewRecorder()
  ctx := core.NewContext(w, req)
  
  // Test handler
  controller := &TestController{}
  err := controller.GetTest(ctx)
  
  assert.NoError(t, err)
  assert.Equal(t, 200, ctx.StatusCode())
}

Best Practices

  1. Single Responsibility: Each module should have a single, well-defined purpose
  2. Dependency Direction: Dependencies should flow inward (controllers → services → repositories)
  3. Lifecycle Management: Use lifecycle hooks for initialization and cleanup
  4. Error Handling: Always return errors from handlers for proper middleware handling
  5. Metadata Storage: Use the metadata system for cross-cutting concerns

Next Steps

  • Explore the DI Module for advanced dependency injection
  • Check out Validation for request validation
  • Learn about Guards for route protection
  • See Interceptors for request/response transformation

License

MIT

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ApplicationOption

type ApplicationOption func(*NestApplication)

ApplicationOption configures the NestApplication

func WithIdleTimeout

func WithIdleTimeout(timeout time.Duration) ApplicationOption

WithIdleTimeout sets the HTTP server idle timeout

func WithPort

func WithPort(port int) ApplicationOption

WithPort sets the server port

func WithReadTimeout

func WithReadTimeout(timeout time.Duration) ApplicationOption

WithReadTimeout sets the HTTP server read timeout

func WithShutdownTimeout

func WithShutdownTimeout(timeout time.Duration) ApplicationOption

WithShutdownTimeout sets the graceful shutdown timeout

func WithWriteTimeout

func WithWriteTimeout(timeout time.Duration) ApplicationOption

WithWriteTimeout sets the HTTP server write timeout

type Context

type Context struct {
	Request  *http.Request
	Response http.ResponseWriter
	// contains filtered or unexported fields
}

Context represents the request context with helper methods

func NewContext

func NewContext(w http.ResponseWriter, r *http.Request) *Context

NewContext creates a new request context

func (*Context) BindJSON

func (c *Context) BindJSON(obj any) error

BindJSON binds the request body to a struct

func (*Context) Body

func (c *Context) Body() ([]byte, error)

Body returns the raw request body

func (*Context) Context

func (c *Context) Context() context.Context

Context returns the underlying context.Context

func (*Context) Data

func (c *Context) Data(code int, contentType string, data []byte) error

Data sends raw bytes as response

func (*Context) Get

func (c *Context) Get(key string) any

Get retrieves metadata from the context

func (*Context) GetBool

func (c *Context) GetBool(key string) bool

GetBool retrieves a bool metadata from the context

func (*Context) GetInt

func (c *Context) GetInt(key string) int

GetInt retrieves an int metadata from the context

func (*Context) GetString

func (c *Context) GetString(key string) string

GetString retrieves a string metadata from the context

func (*Context) HTML

func (c *Context) HTML(code int, html string) error

HTML sends an HTML response

func (*Context) Header

func (c *Context) Header(name string) string

Header returns a request header by name

func (*Context) JSON

func (c *Context) JSON(code int, obj any) error

JSON sends a JSON response

func (*Context) Method

func (c *Context) Method() string

Method returns the HTTP method

func (*Context) Param

func (c *Context) Param(name string) string

Param returns a path parameter by name

func (*Context) Path

func (c *Context) Path() string

Path returns the request path

func (*Context) Query

func (c *Context) Query(name string) string

Query returns a query parameter by name

func (*Context) QueryDefault

func (c *Context) QueryDefault(name, defaultValue string) string

QueryDefault returns a query parameter with a default value

func (*Context) Reset

func (c *Context) Reset(w http.ResponseWriter, r *http.Request)

Reset resets the context for reuse

func (*Context) Set

func (c *Context) Set(key string, value any)

Set stores metadata in the context

func (*Context) SetContext

func (c *Context) SetContext(ctx context.Context)

SetContext sets the underlying context.Context

func (*Context) SetHeader

func (c *Context) SetHeader(name, value string)

SetHeader sets a response header

func (*Context) SetParam

func (c *Context) SetParam(name, value string)

SetParam sets a path parameter

func (*Context) Status

func (c *Context) Status(code int) *Context

Status sets the HTTP status code

func (*Context) StatusCode

func (c *Context) StatusCode() int

StatusCode returns the response status code

func (*Context) String

func (c *Context) String(code int, format string, values ...any) error

String sends a plain text response

type Controller

type Controller interface {
	Routes() []RouteDefinition
}

Controller represents a request handler with routes

type ControllerMetadata

type ControllerMetadata struct {
	Path        string
	Tags        []string
	Description string
}

ControllerMetadata stores controller-specific metadata

type ControllerRef

type ControllerRef struct {
	// contains filtered or unexported fields
}

ControllerRef represents a controller instance

type HandlerFunc

type HandlerFunc func(*Context) error

HandlerFunc is the signature for route handlers

type LifecycleHookOrder

type LifecycleHookOrder int

LifecycleHookOrder defines the order of lifecycle hooks

const (
	// OnModuleInitOrder - called when module dependencies are resolved
	OnModuleInitOrder LifecycleHookOrder = iota

	// OnApplicationBootstrapOrder - called when all modules are initialized
	OnApplicationBootstrapOrder

	// OnModuleDestroyOrder - called when module is being destroyed
	OnModuleDestroyOrder

	// OnApplicationShutdownOrder - called before application shutdown
	OnApplicationShutdownOrder
)

func (LifecycleHookOrder) String

func (o LifecycleHookOrder) String() string

String returns the string representation of lifecycle hook order

type LifecycleManager

type LifecycleManager struct {
	// contains filtered or unexported fields
}

LifecycleManager manages application and module lifecycle hooks

func NewLifecycleManager

func NewLifecycleManager() *LifecycleManager

NewLifecycleManager creates a new lifecycle manager

func (*LifecycleManager) CallOnApplicationBootstrap

func (lm *LifecycleManager) CallOnApplicationBootstrap(ctx context.Context) error

CallOnApplicationBootstrap calls OnApplicationBootstrap on all components

func (*LifecycleManager) CallOnApplicationShutdown

func (lm *LifecycleManager) CallOnApplicationShutdown(ctx context.Context) error

CallOnApplicationShutdown calls OnApplicationShutdown on all components

func (*LifecycleManager) CallOnModuleDestroy

func (lm *LifecycleManager) CallOnModuleDestroy(ctx context.Context) error

CallOnModuleDestroy calls OnModuleDestroy on all modules and their providers

func (*LifecycleManager) CallOnModuleInit

func (lm *LifecycleManager) CallOnModuleInit(ctx context.Context) error

CallOnModuleInit calls OnModuleInit on all modules and their providers

func (*LifecycleManager) RegisterModule

func (lm *LifecycleManager) RegisterModule(module *ModuleRef)

RegisterModule registers a module for lifecycle management

type MetadataKey

type MetadataKey string

MetadataKey is a type for metadata keys

const (
	// MetadataKeyCONTROLLER marks a type as a controller
	MetadataKeyCONTROLLER MetadataKey = "controller"

	// MetadataKeyROUTE stores route information
	MetadataKeyROUTE MetadataKey = "route"

	// MetadataKeyGUARD stores guard information
	MetadataKeyGUARD MetadataKey = "guard"

	// MetadataKeyINTERCEPTOR stores interceptor information
	MetadataKeyINTERCEPTOR MetadataKey = "interceptor"

	// MetadataKeyPIPE stores pipe information
	MetadataKeyPIPE MetadataKey = "pipe"

	// MetadataKeyPARAM stores parameter information
	MetadataKeyPARAM MetadataKey = "param"

	// MetadataKeySWAGGER stores swagger documentation
	MetadataKeySWAGGER MetadataKey = "swagger"
)

type MetadataStorage

type MetadataStorage struct {
	// contains filtered or unexported fields
}

MetadataStorage stores metadata for types

func NewMetadataStorage

func NewMetadataStorage() *MetadataStorage

NewMetadataStorage creates a new metadata storage

func (*MetadataStorage) Clear

func (ms *MetadataStorage) Clear(target any)

Clear removes all metadata for a type

func (*MetadataStorage) Delete

func (ms *MetadataStorage) Delete(target any, key MetadataKey)

Delete removes metadata for a type and key

func (*MetadataStorage) Get

func (ms *MetadataStorage) Get(target any, key MetadataKey) (any, bool)

Get retrieves metadata for a type

func (*MetadataStorage) GetAll

func (ms *MetadataStorage) GetAll(target any) map[MetadataKey]any

GetAll retrieves all metadata for a type

func (*MetadataStorage) Has

func (ms *MetadataStorage) Has(target any, key MetadataKey) bool

Has checks if metadata exists for a type and key

func (*MetadataStorage) Set

func (ms *MetadataStorage) Set(target any, key MetadataKey, value any)

Set stores metadata for a type

type MiddlewareFunc

type MiddlewareFunc func(HandlerFunc) HandlerFunc

MiddlewareFunc is the signature for middleware functions

type Module

type Module interface {
	Configure(builder *ModuleBuilder)
}

Module defines the interface that all modules must implement

type ModuleBuilder

type ModuleBuilder struct {
	// contains filtered or unexported fields
}

ModuleBuilder helps build module configurations

func (*ModuleBuilder) Controllers

func (b *ModuleBuilder) Controllers(controllers ...any) *ModuleBuilder

Controllers adds controllers to the module

func (*ModuleBuilder) Exports

func (b *ModuleBuilder) Exports(exports ...any) *ModuleBuilder

Exports marks providers as exportable to other modules

func (*ModuleBuilder) Imports

func (b *ModuleBuilder) Imports(modules ...Module) *ModuleBuilder

Imports adds modules to be imported

func (*ModuleBuilder) Providers

func (b *ModuleBuilder) Providers(providers ...Provider) *ModuleBuilder

Providers adds providers to the module

type ModuleCompiler

type ModuleCompiler struct {
	// contains filtered or unexported fields
}

ModuleCompiler compiles modules into executable units

func NewModuleCompiler

func NewModuleCompiler() *ModuleCompiler

NewModuleCompiler creates a new module compiler

func (*ModuleCompiler) Compile

func (mc *ModuleCompiler) Compile(module Module) (*ModuleRef, error)

Compile compiles a module and its dependencies

func (*ModuleCompiler) Get

func (mc *ModuleCompiler) Get(module Module) (*ModuleRef, bool)

Get retrieves a compiled module by type

func (*ModuleCompiler) GetAll

func (mc *ModuleCompiler) GetAll() []*ModuleRef

GetAll returns all compiled modules

type ModuleMetadata

type ModuleMetadata struct {
	// contains filtered or unexported fields
}

ModuleMetadata stores module metadata

type ModuleRef

type ModuleRef struct {
	// contains filtered or unexported fields
}

ModuleRef represents a compiled module instance

func (*ModuleRef) ExportProvider

func (mr *ModuleRef) ExportProvider(providerType reflect.Type, instance any)

ExportProvider marks a provider as exported

func (*ModuleRef) GetControllers

func (mr *ModuleRef) GetControllers() []ControllerRef

GetControllers returns all controllers in the module

func (*ModuleRef) GetProvider

func (mr *ModuleRef) GetProvider(providerType reflect.Type) (any, bool)

GetProvider retrieves a provider from the module

func (*ModuleRef) Name

func (mr *ModuleRef) Name() string

Name returns the module name

func (*ModuleRef) RegisterController

func (mr *ModuleRef) RegisterController(instance any) error

RegisterController registers a controller in the module

func (*ModuleRef) RegisterProvider

func (mr *ModuleRef) RegisterProvider(providerType reflect.Type, instance any)

RegisterProvider registers a provider in the module

type NestApplication

type NestApplication struct {
	// contains filtered or unexported fields
}

NestApplication is the main application instance

func (*NestApplication) Close

func (app *NestApplication) Close() error

Close gracefully shuts down the application

func (*NestApplication) GetMetadata

func (app *NestApplication) GetMetadata() *MetadataStorage

GetMetadata returns the metadata storage

func (*NestApplication) GetRouter

func (app *NestApplication) GetRouter() *Router

GetRouter returns the application router

func (*NestApplication) Listen

func (app *NestApplication) Listen(addr string) error

Listen starts the HTTP server

type NestFactory

type NestFactory struct{}

NestFactory creates NestJS-style applications

func (NestFactory) Create

func (f NestFactory) Create(rootModule Module, opts ...ApplicationOption) *NestApplication

Create creates a new NestApplication with the root module

type OnApplicationBootstrap

type OnApplicationBootstrap interface {
	OnApplicationBootstrap(ctx context.Context) error
}

OnApplicationBootstrap lifecycle hook called when application starts

type OnApplicationShutdown

type OnApplicationShutdown interface {
	OnApplicationShutdown(ctx context.Context) error
}

OnApplicationShutdown lifecycle hook called before application stops

type OnModuleDestroy

type OnModuleDestroy interface {
	OnModuleDestroy(ctx context.Context) error
}

OnModuleDestroy lifecycle hook called when module is destroyed

type OnModuleInit

type OnModuleInit interface {
	OnModuleInit(ctx context.Context) error
}

OnModuleInit lifecycle hook called when module is initialized

type ParameterMetadata

type ParameterMetadata struct {
	Name        string
	Type        string // "query", "path", "body", "header"
	Required    bool
	Description string
	Schema      any
}

ParameterMetadata stores parameter-specific metadata

type Provider

type Provider any

Provider represents a dependency that can be injected

type RouteDefinition

type RouteDefinition struct {
	Method      string
	Path        string
	Handler     HandlerFunc
	Middlewares []MiddlewareFunc
}

RouteDefinition defines a single route with its configuration

type RouteMetadata

type RouteMetadata struct {
	Method      string
	Path        string
	Summary     string
	Description string
	Tags        []string
	Deprecated  bool
}

RouteMetadata stores route-specific metadata

type Router

type Router struct {
	// contains filtered or unexported fields
}

Router manages HTTP routes

func NewRouter

func NewRouter() *Router

NewRouter creates a new router

func (*Router) Delete

func (r *Router) Delete(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Delete registers a DELETE route

func (*Router) Get

func (r *Router) Get(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Get registers a GET route

func (*Router) Head

func (r *Router) Head(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Head registers a HEAD route

func (*Router) Options

func (r *Router) Options(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Options registers an OPTIONS route

func (*Router) Patch

func (r *Router) Patch(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Patch registers a PATCH route

func (*Router) Post

func (r *Router) Post(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Post registers a POST route

func (*Router) Put

func (r *Router) Put(path string, handler HandlerFunc, middlewares ...MiddlewareFunc)

Put registers a PUT route

func (*Router) Register

func (r *Router) Register(route RouteDefinition)

Register registers a route

func (*Router) ServeHTTP

func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request)

ServeHTTP implements http.Handler

func (*Router) Use

func (r *Router) Use(middleware MiddlewareFunc)

Use applies middleware globally

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL