### Basic Velocity App Setup Source: https://github.com/velocitykode/velocity/blob/main/README.md A minimal Velocity application demonstrating how to initialize the framework and define a simple GET route. This example sets up a basic HTTP server that responds with JSON. ```go package main import ( "log" "github.com/velocitykode/velocity" "github.com/velocitykode/velocity/router" ) func main() { v, err := velocity.New() if err != nil { log.Fatal(err) } v.Router.Get("/", func(c *router.Context) error { return c.JSON(200, map[string]string{"hello": "world"}) }) if err := v.Serve(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Setup Test Environment with .env.testing Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Configure your test environment by creating a .env.testing file. This example shows settings for an in-memory SQLite database. ```env APP_ENV=testing DB_DRIVER=sqlite DB_DATABASE=:memory: # Or use a dedicated test database: # DB_DRIVER=postgres # DB_DATABASE=myapp_test # DB_HOST=localhost # DB_USERNAME=postgres # DB_PASSWORD=secret ``` -------------------------------- ### Install Velocity CLI Source: https://github.com/velocitykode/velocity/blob/main/README.md Install the Velocity CLI using Homebrew. This is the recommended way to get started with Velocity. ```bash brew tap velocitykode/tap && brew install velocity ``` -------------------------------- ### Manual Release Steps Example Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md Shows the manual steps required to prepare for an automated release, including updating the changelog and pushing changes. ```bash # Update CHANGELOG.md with the release entry. git commit -m "docs(changelog): prepare v1.5.0" git push origin main # CI tags and publishes automatically. ``` -------------------------------- ### Faker Library Examples Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Demonstrates various functions available from the gofakeit library for generating realistic test data within factories. ```go faker := ormtesting.Faker() faker.Name() // "John Doe" faker.Email() // "john@example.com" faker.Phone() // "+1-555-0123" faker.City() // "San Francisco" faker.Sentence(5) // Random sentence faker.Paragraph(3,5,10," ") // Random paragraph faker.UUID() // "550e8400-e29b..." faker.Number(1, 100) // Random number faker.Bool() // true or false ``` -------------------------------- ### Go Documentation Comment Example Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Shows how to write godoc comments for exported functions and packages in Go. ```go // Cache provides a unified interface for caching operations. // It supports multiple drivers (memory, file, redis) configured // via the CACHE_DRIVER environment variable. package cache // Get retrieves a value from the cache by key. // It returns an error if the key doesn't exist or has expired. // // Example: // value, err := cache.Get("user:123") // if err != nil { // log.Error("Cache miss", err) // } func Get(key string) (interface{}, error) { // Implementation } ``` -------------------------------- ### Table-Driven Test Example in Go Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Illustrates writing table-driven tests in Go for testing multiple scenarios of a function. ```go func TestCacheSet(t *testing.T) { tests := []struct { name string key string value interface{} wantErr bool }{ {"valid string", "key1", "value1", false}, {"valid int", "key2", 42, false}, {"empty key", "", "value", true}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { cache := NewMemoryCache() err := cache.Set(tt.key, tt.value, 60*time.Second) if (err != nil) != tt.wantErr { t.Errorf("Set() error = %v, wantErr %v", err, tt.wantErr) } }) } } ``` -------------------------------- ### Factory Chaining Example Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Demonstrates chaining multiple factory methods to create complex test data with specific states, counts, and sequential values. ```go UserFactory(). Count(50). State("verified"). Sequence("email", func(i int) interface{} { return fmt.Sprintf("user%d@test.com", i) }). Create(map[string]interface{}{ "created_at": time.Now(), }) ``` -------------------------------- ### Integration Test Setup in Go Source: https://github.com/velocitykode/velocity/blob/main/TESTING.md Sets up integration tests by checking required environment variables before running tests. Exits with an error if dependencies are missing, ensuring tests fail loudly. ```go //go:build integration package foo var requiredEnv = []string{"POSTGRES_URL", "REDIS_HOST"} func TestMain(m *testing.M) { var missing []string for _, name := range requiredEnv { if os.Getenv(name) == "" { missing = append(missing, name) } } if len(missing) > 0 { fmt.Fprintf(os.Stderr, "integration tests require env vars (missing: %s) — use `make test-integration`\n", strings.Join(missing, ", ")) os.Exit(1) } os.Exit(m.Run()) } ``` -------------------------------- ### Local Development Environment Variables Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Example `.env` file for local development. Sets default drivers for logging, caching, and queuing. ```env LOG_DRIVER=console CACHE_DRIVER=memory QUEUE_DRIVER=memory ``` -------------------------------- ### Create and Serve a New Velocity App Source: https://github.com/velocitykode/velocity/blob/main/README.md Create a new Velocity project and start the development server. This command scaffolds a new application and launches it. ```bash velocity new myapp && cd myapp && vel serve ``` -------------------------------- ### TableBuilder API Examples Source: https://github.com/velocitykode/velocity/blob/main/orm/migrate/README.md Demonstrates various methods available in the `TableBuilder` DSL for defining primary keys, column types, and modifiers like unique constraints, nullability, and default values. ```go // Primary Keys t.ID() // Auto-increment integer primary key t.UUIDPrimary() // UUID primary key with auto-generation // Column Types t.String("name") // VARCHAR(255) t.String("code", 10) // VARCHAR(10) t.Text("bio") // TEXT (unlimited) t.Integer("count") // INTEGER t.BigInteger("views") // BIGINT t.Boolean("active") // BOOLEAN t.UUID("external_id") // UUID column t.Timestamp("verified_at") // Single TIMESTAMP column t.Date("birth_date") // DATE t.Timestamps() // created_at, updated_at t.SoftDeletes() // deleted_at (nullable) // Modifiers t.String("email").Unique() // UNIQUE constraint t.String("bio").Nullable() // Allow NULL t.Integer("status").Default(0) // Default value ``` -------------------------------- ### Deprecated Function Example Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md Illustrates how a deprecated API is marked with a godoc comment and indicates it will not be removed. ```go // Deprecated: use ctx.JSON instead. Will not be removed. func (c *Context) Json(code int, v any) error { ... } ``` -------------------------------- ### Running Fuzz Targets in Go Source: https://github.com/velocitykode/velocity/blob/main/TESTING.md Example command to run a specific fuzz target for an extended duration locally. Useful for deeper testing when modifying fuzz targets. ```bash go test -run ^$ -fuzz FuzzSanitizeRedirect -fuzztime=5m ./router/ ``` -------------------------------- ### Define a User Factory Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Create a factory for generating user data using the ORM testing utilities. This example includes defining states and using Faker for realistic data. ```go package tests import ormtesting "github.com/velocitykode/velocity/orm/testing" func UserFactory() *ormtesting.Factory { faker := ormtesting.Faker() factory := ormtesting.NewFactory("users", func() map[string]interface{} { return map[string]interface{}{ "name": faker.Name(), "email": faker.Email(), } }) factory.DefineState("admin", map[string]interface{}{ "role": "admin", }) return factory } ``` -------------------------------- ### LazyRefreshDatabase Usage Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Example of using LazyRefreshDatabase in a test. This method is recommended for most tests due to its performance benefits. ```go func TestSomething(t *testing.T) { tc := ormtesting.NewTestCase(t) tc.LazyRefreshDatabase() // Test runs in transaction - rolled back automatically UserFactory().Count(100).Create() } ``` -------------------------------- ### Upgrading Dependencies Transitively with Go Modules Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md Use `go get -u` to upgrade dependencies, including transitive ones, to their latest versions. ```bash # Upgrade dependencies transitively. go get -u github.com/velocitykode/velocity ``` -------------------------------- ### Explicitly Requesting a Specific Pre-release Version Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md When using `go get`, pre-release versions are only selected if explicitly requested by tag. ```bash go get github.com/velocitykode/velocity@v1.5.0-rc.1 ``` -------------------------------- ### Tagging Pre-release Versions in Git Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md Use these git commands to tag pre-release versions for early testing. Pre-release tags are not automatically picked up by `go get ...@latest` and must be explicitly requested. ```bash git tag v1.5.0-alpha.1 # early integration testing git tag v1.5.0-beta.1 # feature-complete, seeking feedback git tag v1.5.0-rc.1 # release candidate git tag v1.5.0 # stable ``` -------------------------------- ### Performing a Safe Upgrade with Go Modules Source: https://github.com/velocitykode/velocity/blob/main/RELEASES.md Use `go get ...@latest` for safe upgrades that never cross a major version boundary. Follow with `go mod tidy` to clean up. ```bash # Safe upgrade — never crosses a major boundary. go get github.com/velocitykode/velocity@latest go mod tidy ``` -------------------------------- ### Migrator Commands for Up, Down, and Status Source: https://github.com/velocitykode/velocity/blob/main/orm/migrate/README.md Provides examples of using the `Migrator` to run pending migrations (`Up`), rollback the last batch of migrations (`Down`), and check the status of all registered migrations. ```go migrator := migrate.NewMigrator(manager.DB(), manager.DriverName()) // Run pending migrations migrator.Up() // Rollback last batch migrator.Down(1) // Check status statuses, _ := migrator.Status() for _, s := range statuses { fmt.Printf("%s: %s\n", s.Version, s.State) } ``` -------------------------------- ### Conventional Commits Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Examples of commit messages following the conventional commit format. Use prefixes like 'feat:', 'fix:', 'docs:' for clarity. ```bash git commit -m "feat: Add new cache driver for Memcached" # or git commit -m "fix: Resolve race condition in queue worker" ``` -------------------------------- ### Perform CRUD Operations with Velocity ORM Models Source: https://context7.com/velocitykode/velocity/llms.txt Examples demonstrate finding records by primary key, using the chainable query builder for complex queries, pagination, creating, saving, soft deleting, restoring, hard deleting, bulk updates, and executing raw SQL. ```go // Find by PK user, err := User{}.Find(42) // Chainable query builder — returns []User activeUsers, err := User{}. Where("status = ?", true). OrderBy("created_at", "DESC"). Limit(10). With("Posts"). Get() // Paginate page, err := User{}. Where("email LIKE ?", "%@example.com"). Paginate(1, 20) // page.Data []User, page.Total int, page.LastPage int // Create u, err := User{}.Create(map[string]any{ "name": "Alice", "email": "alice@example.com", "password": orm.Hash("secret"), }) // Save (insert or update) u.Name = "Alice Smith" err = orm.Save(nil, u) // Soft delete (sets deleted_at) err = u.Delete() // Restore soft-deleted record err = u.Restore() // Hard delete err = u.ForceDelete() // Bulk update affected, err := User{}.Update( map[string]any{"active": false}, // WHERE map[string]any{"email_verified": true}, // SET ) // Raw SQL var results []User err = User{}.Raw("SELECT * FROM users WHERE created_at > ?", "2024-01-01").Get(&results) _ = user _ = activeUsers _ = page _ = u _ = affected _ = err ``` -------------------------------- ### Add Velocity to an Existing Project Source: https://github.com/velocitykode/velocity/blob/main/README.md Add the Velocity framework to an existing Go project using go get. This fetches the latest version of the Velocity package. ```bash go get github.com/velocitykode/velocity@latest ``` -------------------------------- ### RefreshDatabase Usage Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Example of using RefreshDatabase in a test. This method ensures a completely fresh database state for each test by dropping and recreating tables. ```go func TestSomething(t *testing.T) { tc := ormtesting.NewTestCase(t) tc.RefreshDatabase() // Completely fresh database } ``` -------------------------------- ### Advanced Velocity App Configuration Source: https://github.com/velocitykode/velocity/blob/main/README.md Configure a Velocity application with middleware, routes, event listeners, and more. This approach allows for modular application setup by chaining configuration methods. ```go func main() { v, _ := velocity.New() if err := v. Middleware(app.Middleware(v)). // your global/web/API middleware stacks Routes(routes.Register). // your route definitions Events(app.Events(v.Log)). // your event listeners Schedule(schedule.Configure). // your scheduled jobs Exceptions(app.ExceptionHandler). // your custom error handler Run(); err != nil { // serves HTTP, or runs a `vel ...` command log.Fatal(err) } } ``` -------------------------------- ### Type-Safe ORM Query Example Source: https://github.com/velocitykode/velocity/blob/main/README.md Example of a type-safe ORM query in Velocity. This query retrieves active users, ordered by creation date, and limits the results. The ORM ensures type safety at compile time. ```go users, _ := User{}.Where("active = ?", true). OrderBy("created_at", "DESC"). Limit(10). Get() ``` -------------------------------- ### Download Go Dependencies Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Downloads all the necessary Go modules and dependencies for the project. ```bash go mod download ``` -------------------------------- ### Run Go Tests Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Commands to execute the test suite. Includes options for race detection and coverage checks. ```bash # Run all tests go test ./... # Run with race detection go test ./... -race # Check coverage go test ./... -cover ``` -------------------------------- ### Goroutine Panic Recovery with async.Go Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Demonstrates the preferred method for handling panics in goroutines using the async.Go utility. ```go // Preferred: async.Go handles recovery and logging. async.Go(func() { if err := server.Run(ctx); err != nil { log.Error("server exited", "error", err) } }) ``` -------------------------------- ### Create and Initialize Velocity Application Source: https://context7.com/velocitykode/velocity/llms.txt Initializes the Velocity framework, reading configuration from environment variables or a `.env` file. Allows overriding specific configuration fields like port and timeouts using option functions. Handles resource cleanup on failure. ```go package main import ( "log" "time" "github.com/velocitykode/velocity" "github.com/velocitykode/velocity/router" ) func main() { // Option 1: zero-config — reads from .env / env vars v, err := velocity.New() if err != nil { log.Fatal(err) } // Option 2: override specific fields at construction time v, err = velocity.New( velocity.WithPort("8080"), velocity.WithReadTimeout(15*time.Second), velocity.WithWriteTimeout(15*time.Second), ) if err != nil { log.Fatal(err) } v.Router.Get("/health", func(c *router.Context) error { return c.JSON(200, map[string]string{"status": "ok", "version": v.Version()}) }) // v.Serve() starts HTTP when os.Args has no extra args, // or dispatches CLI commands (vel migrate, vel queue:work, …) otherwise. if err := v.Serve(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Declarative Bootstrap Chain Configuration Source: https://context7.com/velocitykode/velocity/llms.txt Configures the application's middleware, routes, event listeners, scheduled tasks, and exception handlers using a fluent API. Callbacks are executed in order during `Serve()` or `Run()`. All callbacks are optional. ```go package main import ( "log" "github.com/velocitykode/velocity" "github.com/velocitykode/velocity/chain" "github.com/velocitykode/velocity/events" "github.com/velocitykode/velocity/router" "github.com/velocitykode/velocity/scheduler" "github.com/velocitykode/velocity/exceptions" ) func main() { v, err := velocity.New() if err != nil { log.Fatal(err) } err = v. Middleware(func(m *chain.MiddlewareStack) { // Apply CORS and rate-limiting to every API route cors := router.DefaultCORSConfig() cors.AllowedOrigins = []string{"https://app.example.com"} m.API(router.CORS(cors), router.RateLimit(100, 60)) }). Routes(func(r *chain.Routing) { r.Get("/", func(c *router.Context) error { return c.JSON(200, map[string]string{"hello": "world"}) }) // Group with prefix and middleware r.Group("/api/v1", func(api *chain.Routing) { api.Get("/users", listUsersHandler) api.Post("/users", createUserHandler) }) }). Events(func(d events.Dispatcher) { d.Listen("user.registered", func(event any) error { log.Println("new user registered:", event) return nil }) }). Schedule(func(s scheduler.TaskScheduler) { s.Call(func() { log.Println("heartbeat") }).EveryMinute() }). Exceptions(func(h exceptions.ExceptionHandler) { h.Register(func(c *router.Context, err error) { c.JSON(500, map[string]string{"error": err.Error()}) }) }). Serve() if err != nil { log.Fatal(err) } } ``` -------------------------------- ### Factory Basic Methods Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Overview of basic methods available on a factory object for generating and persisting data. ```go factory.Make() // Generate in-memory (no DB) factory.Create() // Generate and persist to DB factory.Count(10) // Generate 10 records factory.State("admin") // Apply named state factory.Sequence("email", fn) // Sequential values ``` -------------------------------- ### Go Test Function Naming Conventions Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Demonstrates standard naming conventions for different types of Go tests and benchmarks. ```go func TestFunctionName(t *testing.T) { } // Basic test ``` ```go func TestFunctionName_EdgeCase(t *testing.T) { } // Specific scenario ``` ```go func TestFunctionName_Concurrent(t *testing.T) { } // Concurrency test ``` ```go func BenchmarkFunctionName(b *testing.B) { } // Benchmark ``` -------------------------------- ### Goroutine Panic Recovery with defer recover() Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Shows how to manually handle panics in goroutines by using defer recover() and dispatching a typed failure event. ```go // When you need to dispatch a typed failure event on panic: go func(n interface{}) { defer func() { if r := recover(); r != nil { err := panicerr.FromRecovered(r) m.dispatchEvent(buildNotificationFailed(ctx, n, notification, "", err)) errChan <- fmt.Errorf("velocity/notification: send many panic: %w", err) } }() // ... work ... }(notifiable) ``` -------------------------------- ### Run Tests with Verbose Output Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Runs Go tests with verbose output enabled, showing details for each test case. ```bash go test ./pkg/log -v ``` -------------------------------- ### Run Migrations with Velocity ORM Source: https://github.com/velocitykode/velocity/blob/main/orm/migrate/README.md Initialize the Velocity ORM manager and then create a migrator instance to run pending migrations. Ensure your migration files are imported to register them. ```go import ( "github.com/velocitykode/velocity/orm" "github.com/velocitykode/velocity/orm/migrate" _ "myapp/migrations" // Import to register ) // Initialize ORM via the Manager manager, err := orm.NewManager(orm.Config{ Driver: "sqlite", Database: "./database.db", }) // Run migrations migrator := migrate.NewMigrator(manager.DB(), manager.DriverName()) err = migrator.Up() ``` -------------------------------- ### Test Posts Index Endpoint Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md This Go test function demonstrates how to set up a test environment using `ormtesting.RefreshDatabase`, create test data with factories, and then test an HTTP endpoint. It asserts the response code and the number of posts returned. ```go func TestPostsIndex(t *testing.T) { ormtesting.RefreshDatabase(t) // Setup user := UserFactory().Create() userID := user.(map[string]interface{})["id"] PostFactory().Count(3).Create(map[string]interface{}{ "user_id": userID, "published": true, }) // Test router := gin.New() router.GET("/posts", controllers.PostsIndex) w := httptest.NewRecorder() req := httptest.NewRequest("GET", "/posts", nil) router.ServeHTTP(w, req) // Assert assert.Equal(t, 200, w.Code) var posts []map[string]interface{} json.Unmarshal(w.Body.Bytes(), &posts) assert.Equal(t, 3, len(posts)) } ``` -------------------------------- ### Register HTTP Routes with Velocity Router Source: https://context7.com/velocitykode/velocity/llms.txt Registers HTTP routes using methods like Get, Post, Put, Patch, and Delete. Route handlers receive a `*router.Context` for parameter extraction, request binding, and response helpers. Each route registration returns a `RouteConfig` for naming or applying middleware. ```go package main import ( "errors" "log" "github.com/velocitykode/velocity" "github.com/velocitykode/velocity/router" "github.com/velocitykode/velocity/orm" ) type User struct { orm.Model[User] Name string `json:"name"` Email string `json:"email"` } func main() { v, _ := velocity.New() // Named route with URL parameter v.Router.Get("/users/:id", func(c *router.Context) error { id, err := c.ParamInt("id") if err != nil { return c.BadRequest("invalid user id") } user, err := User{}.Find(id) if errors.Is(err, orm.ErrRecordNotFound) { return c.NotFound("user not found") } if err != nil { return err } return c.JSON(200, user) }).Name("users.show") // POST with JSON binding and validation v.Router.Post("/users", func(c *router.Context) error { if err := c.Validate(map[string][]string{ "name": {"required", "min:2", "max:100"}, "email": {"required", "email", "unique:users,email"}, }); err != nil { return err // ErrValidationAborted: redirect already written } var input struct { Name string `json:"name"` Email string `json:"email"` } if err := c.Bind(&input); err != nil { return c.BadRequest(err.Error()) } user, err := User{}.Create(map[string]any{ "name": input.Name, "email": input.Email, }) if err != nil { return err } return c.JSON(201, user) }) // DELETE with int64 param v.Router.Delete("/users/:id", func(c *router.Context) error { id, err := c.ParamInt64("id") if err != nil { return c.BadRequest("invalid id") } _, err = User{}.DeleteWhere(map[string]any{"id": id}) if err != nil { return err } return c.NoContent() }) log.Fatal(v.Serve()) } ``` -------------------------------- ### Cache Management with Velocity Source: https://context7.com/velocitykode/velocity/llms.txt Demonstrates using the cache manager for storing and retrieving data, including caching expensive computations with `Remember` and invalidating cache with `Forget`. Also shows low-level operations like `Increment`, `Put`, and `GetString`. ```go // CACHE_DRIVER=redis (or memory, file, database) // REDIS_HOST=127.0.0.1 // REDIS_PORT=6379 v.Router.Get("/products", func(c *router.Context) error { // Cache for 5 minutes; recompute on miss result, err := c.Cache().Remember("products:all", 5*time.Minute, func() interface{} { products, _ := Product{}.OrderBy("name", "ASC").Get() return products }) if err != nil { return err } return c.JSON(200, result) }) v.Router.Post("/products", func(c *router.Context) error { // ... create product ... // Invalidate cache on mutation if err := c.Cache().Forget("products:all"); err != nil { return err } return c.JSON(201, map[string]string{"ok": "true"}) }) // Low-level ops v.Router.Get("/counter", func(c *router.Context) error { n, err := c.Cache().Increment("page_views", 1) if err != nil { return err } // Store arbitrary value with TTL c.Cache().Put("last_visit", time.Now().String(), 24*time.Hour) // Retrieve val, ok := c.Cache().GetString("last_visit") return c.JSON(200, map[string]any{"views": n, "last_visit": val, "found": ok}) }) ``` -------------------------------- ### Register and Dispatch Events with events.Dispatcher Source: https://context7.com/velocitykode/velocity/llms.txt Register event listeners during application boot and dispatch events from handlers. Listeners can be synchronous or asynchronous. ```go v.Events(func(d events.Dispatcher) { d.Listen("order.placed", func(event any) error { order := event.(map[string]any) log.Printf("order placed: %v", order["id"]) // send confirmation email, update inventory ... return nil }) d.Listen("user.registered", sendWelcomeEmailListener) d.Listen("user.registered", notifyAdminListener) }) // Dispatch from a handler v.Router.Post("/orders", func(c *router.Context) error { // ... create order ... c.Events().Dispatch("order.placed", map[string]any{ "id": order.ID, "total": order.Total, "userID": order.UserID, }) return c.JSON(201, order) }) ``` -------------------------------- ### Create a New Migration with TableBuilder Source: https://github.com/velocitykode/velocity/blob/main/orm/migrate/README.md Define a new database migration using the `migrate.Register` function. The `Up` function uses the `TableBuilder` DSL to define schema changes, and the `Down` function defines how to revert those changes. ```go package migrations import "github.com/velocitykode/velocity/orm/migrate" func init() { migrate.Register(&migrate.Migration{ Version: "20251009120000", Up: func(m *migrate.Migrator) error { return m.CreateTable("users", func(t *migrate.TableBuilder) { t.ID() t.String("email").Unique() t.String("name") t.Timestamps() }) }, Down: func(m *migrate.Migrator) error { return m.DropTable("users") }, }) } ``` -------------------------------- ### Run Linters Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Command to run the golangci-lint linter. Checks for common code quality issues. ```bash golangci-lint run ``` -------------------------------- ### Handle User Signup with Validation and Queue Source: https://github.com/velocitykode/velocity/blob/main/README.md A Velocity handler that binds JSON input, validates it, saves a user, and queues a welcome email. This demonstrates the integrated validation, ORM, and queueing capabilities. ```go v.Router.Post("/signup", func(c *router.Context) error { var input struct { Email string `json:"email" validate:"required,email"` Name string `json:"name" validate:"required"` } if err := c.Bind(&input); err != nil { return c.BadRequest(err.Error()) } user := models.User{Email: input.Email, Name: input.Name} if err := user.Save(); err != nil { return err } v.Queue.Push(jobs.SendWelcomeEmail{UserID: user.ID}) return c.JSON(201, user) }) ``` -------------------------------- ### Test Application with velocitytest.NewApp Source: https://context7.com/velocitykode/velocity/llms.txt Utilize `velocitytest.NewApp` to create a test application with an in-memory SQLite DB, memory queue, memory cache, and fake event dispatcher. Use `router.TestClient` or `httptest` for making requests. ```go package myapp_test import ( "net/http/httptest" "testing" "github.com/velocitykode/velocity" "github.com/velocitykode/velocity/velocitytest" "github.com/velocitykode/velocity/router" ) func TestHealthEndpoint(t *testing.T) { // Spin up a test app — in-memory DB, no real network app, err := velocitytest.NewApp( velocity.WithoutEvents(), ) if err != nil { t.Fatal(err) } defer app.Shutdown(context.Background()) app.Router.Get("/health", func(c *router.Context) error { return c.JSON(200, map[string]string{"status": "ok"}) }) rec := httptest.NewRecorder() req := httptest.NewRequest("GET", "/health", nil) app.Router.ServeHTTP(rec, req) if rec.Code != 200 { t.Fatalf("expected 200, got %d", rec.Code) } } func TestCreateUser(t *testing.T) { app, _ := velocitytest.NewApp() defer app.Shutdown(context.Background()) // Run migrations against the test SQLite DB // app.DB.Raw(ctx, "CREATE TABLE users ...") app.Router.Post("/users", createUserHandler) body := strings.NewReader(`{"name":"Alice","email":"alice@example.com"}`) req := httptest.NewRequest("POST", "/users", body) req.Header.Set("Content-Type", "application/json") rec := httptest.NewRecorder() app.Router.ServeHTTP(rec, req) if rec.Code != 201 { t.Fatalf("expected 201 got %d: %s", rec.Code, rec.Body) } } ``` -------------------------------- ### Session Authentication: Login Handler Source: https://context7.com/velocitykode/velocity/llms.txt Handles user login using session-based authentication. It binds credentials, attempts authentication, and returns a success or unauthorized response. ```go // --- Session guard (cookie-based) --- v.Router.Post("/login", func(c *router.Context) error { var creds struct { Email string `json:"email"` Password string `json:"password"` Remember bool `json:"remember"` } if err := c.Bind(&creds); err != nil { return c.BadRequest(err.Error()) } ok, err := c.Auth().Attempt(c.Response, c.Request, map[string]interface{}{ "email": creds.Email, "password": creds.Password, }, creds.Remember) if err != nil || !ok { return c.Unauthorized("invalid credentials") } return c.JSON(200, map[string]string{"message": "logged in"}) }) ``` -------------------------------- ### ORM Model Mass-Assignment and Hooks Source: https://context7.com/velocitykode/velocity/llms.txt Demonstrates how to define fillable fields for mass-assignment and implement ORM lifecycle hooks like BeforeCreate and AfterCreate on a model. ```APIDOC ## ORM Model Mass-Assignment and Hooks ### Description Implement lifecycle hooks on your model struct and mass-assignment protection via the `Fillable` or `Guarded` interfaces. ### Model Definition ```go type Article struct { orm.SoftDeleteModel[Article] Title string `json:"title"` Slug string `json:"slug"` AuthorID uint `json:"author_id"` Secret string `json:"secret"` // should not be mass-assignable } ``` ### Fillable Fields Define which fields are allowed for mass-assignment. ```go // Only these fields may be mass-assigned (Create / Update via map) func (Article) Fillable() []string { return []string{"title", "slug", "author_id"} } ``` ### Lifecycle Hooks Implement methods for ORM events. ```go // Hooks: BeforeCreate, AfterCreate, BeforeUpdate, AfterUpdate, BeforeDelete, AfterDelete func (a *Article) BeforeCreate() error { if a.Slug == "" { a.Slug = slugify(a.Title) // auto-generate slug } return nil } func (a *Article) AfterCreate() error { log.Printf("article created: id=%d title=%q", a.ID, a.Title) return nil } ``` ### Usage Example Shows how mass-assignment protection works. ```go // Usage — Secret is silently ignored because it is not in Fillable article, err := Article{}.Create(map[string]any{ "title": "Hello World", "author_id": 1, "secret": "ignored", // stripped by mass-assignment protection }) _ = article _ = err ``` ``` -------------------------------- ### Implementing Background Jobs with Velocity Queue Source: https://context7.com/velocitykode/velocity/llms.txt Defines a background job by implementing the `queue.Job` interface and shows how to register it for deserialization. Jobs can be dispatched using `c.Queue().PushCtx`. ```go package jobs import ( "encoding/json" "log" "time" "github.com/velocitykode/velocity/queue" ) // SendWelcomeEmail is a background job type SendWelcomeEmail struct { UserID uint `json:"user_id"` Email string `json:"email"` } func (j SendWelcomeEmail) Handle() error { log.Printf("sending welcome email to %s", j.Email) // ... call mail driver ... return nil } func (j SendWelcomeEmail) Failed(err error) { log.Printf("welcome email failed for user %d: %v", j.UserID, err) } // Optional: set max retries func (j SendWelcomeEmail) MaxAttempts() int { return 3 } // Optional: exponential back-off func (j SendWelcomeEmail) Backoff() []time.Duration { return []time.Duration{5*time.Second, 30*time.Second, 5*time.Minute} } // Register for deserialization (call once at boot) func init() { queue.Register("SendWelcomeEmail", func(data []byte) (queue.Job, error) { var job SendWelcomeEmail return job, json.Unmarshal(data, &job) }) } // --- Dispatching in a handler --- // v.Router.Post("/register", func(c *router.Context) error { // // ... create user ... // ctx := c.Request.Context() // return c.Queue().PushCtx(ctx, jobs.SendWelcomeEmail{UserID: user.ID, Email: user.Email}) // }) ``` -------------------------------- ### Upload and Manage Files with Storage Manager Source: https://context7.com/velocitykode/velocity/llms.txt The `storage.StorageManager` abstracts file operations for local disk, S3, and memory backends. Use `c.Storage().Put` to upload files with specified visibility and MIME type, and `c.Storage().Delete` to remove them. ```go // STORAGE_DRIVER=s3 // AWS_BUCKET=my-bucket // AWS_DEFAULT_REGION=us-east-1 // AWS_ACCESS_KEY_ID=AKIA... // AWS_SECRET_ACCESS_KEY=xxx v.Router.Post("/upload", func(c *router.Context) error { fh, err := c.FormFile("file") if err != nil { return c.BadRequest("missing file") } src, err := fh.Open() if err != nil { return err } defer src.Close() path := "uploads/" + fh.Filename if err := c.Storage().Put(path, src, storage.PutOptions{ Visibility: "public", MimeType: fh.Header.Get("Content-Type"), }); err != nil { return err } url, _ := c.Storage().URL(path) return c.JSON(201, map[string]string{"url": url}) }) v.Router.Delete("/upload/:path", func(c *router.Context) error { path := c.Param("path") if err := c.Storage().Delete(path); err != nil { return err } return c.NoContent() }) ``` -------------------------------- ### Initialize ORM in Test Bootstrap Source: https://github.com/velocitykode/velocity/blob/main/orm/testing/README.md Load the test environment variables and initialize the Velocity ORM in your test bootstrap file. Ensure migrations are imported. ```go package tests import ( "os" "testing" "github.com/joho/godotenv" "github.com/velocitykode/velocity/orm" _ "myapp/migrations" ) func TestMain(m *testing.M) { // Load .env.testing godotenv.Load("../.env.testing") // Initialize from environment orm.Init( os.Getenv("DB_DRIVER"), map[string]any{ "database": os.Getenv("DB_DATABASE"), "host": os.Getenv("DB_HOST"), "username": os.Getenv("DB_USERNAME"), "password": os.Getenv("DB_PASSWORD"), }, ) defer orm.Close() m.Run() } ``` -------------------------------- ### Implement Per-IP Rate Limiting with router.RateLimit Source: https://context7.com/velocitykode/velocity/llms.txt Limits requests per client IP within a sliding window. Optionally uses Redis for distributed enforcement. Apply tighter limits to specific route groups. ```go import "github.com/velocitykode/velocity/router" // 60 requests per 60 seconds per IP (in-memory by default) v.Router.Use(router.RateLimit(60, 60)) ``` ```go // Apply tighter limits to specific route groups v.Router.Group("/api/auth", func(r router.Router) { r.Use(router.RateLimit(5, 60)) // 5 login attempts per minute r.Post("/login", loginHandler) r.Post("/forgot-password", forgotPasswordHandler) }) ``` -------------------------------- ### Load Velocity Configuration from Environment Variables Source: https://context7.com/velocitykode/velocity/llms.txt Loads application configuration from environment variables or an optional `.env` file. This is automatically called by `velocity.New()` but can be invoked directly to inspect or override settings before app initialization. ```go // .env (or real environment variables): // APP_ENV=production // APP_KEY=base64:abc123... // APP_PORT=4000 // DB_CONNECTION=postgres // DB_HOST=localhost // DB_DATABASE=myapp // DB_USERNAME=myapp // DB_PASSWORD=secret // CACHE_DRIVER=redis // REDIS_HOST=127.0.0.1 // QUEUE_DRIVER=redis // MAIL_DRIVER=postmark // MAIL_POSTMARK_TOKEN=tok_xxx package main import ( "fmt" "github.com/velocitykode/velocity" ) func main() { cfg := velocity.ConfigFromEnv() fmt.Println(cfg.Env) // "production" fmt.Println(cfg.DB.Connection) // "postgres" fmt.Println(cfg.Cache.Driver) // "redis" // Pass custom config to New cfg.Port = "9000" v, err := velocity.New(velocity.WithConfig(cfg)) _ = v _ = err } ``` -------------------------------- ### Group Routes with Prefix and Shared Middleware Source: https://context7.com/velocitykode/velocity/llms.txt Organizes routes under a common path prefix and applies shared middleware to all routes within the group. This avoids repeating middleware definitions for each individual route. ```go v.Router.Group("/api/v1", func(api router.Router) { // Auth-protected sub-group api.Group("/admin", func(admin router.Router) { admin.Use(requireAdminMiddleware) admin.Get("/stats", statsHandler) admin.Delete("/users/:id", deleteUserHandler) }) // Public routes api.Post("/login", loginHandler) api.Post("/register", registerHandler) }) // Middleware factory example func requireAdminMiddleware(next router.HandlerFunc) router.HandlerFunc { return func(c *router.Context) error { if c.Cannot("admin") { return c.Forbidden("admin access required") } return next(c) } } ``` -------------------------------- ### Conditional Skip in Go Tests Source: https://github.com/velocitykode/velocity/blob/main/TESTING.md Demonstrates how to conditionally skip a test based on an environment variable. This prevents unconditional skips, which are banned. ```go if os.Getenv("INTEGRATION") == "" { t.Skip("integration tests require INTEGRATION=1") } ``` -------------------------------- ### Format Code with Gofmt Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Standard Go code formatting command. Ensures code adheres to Go conventions. ```bash gofmt -w . ``` -------------------------------- ### RESTful Resource Controller with v.Router.Resource Source: https://context7.com/velocitykode/velocity/llms.txt Maps standard REST actions to HTTP methods and paths. Use `Only` or `Except` to control which routes are generated. ```go type UserController struct{} func (u UserController) Index(c *router.Context) error { users, err := User{}.All() if err != nil { return err } return c.JSON(200, users) } func (u UserController) Show(c *router.Context) error { id, _ := c.ParamInt("id") user, err := User{}.Find(id) if err != nil { return c.NotFound() } return c.JSON(200, user) } func (u UserController) Store(c *router.Context) error { // handle creation return c.JSON(201, map[string]string{"created": "true"}) } func (u UserController) Destroy(c *router.Context) error { id, _ := c.ParamInt("id") User{}.DeleteWhere(map[string]any{"id": id}) return c.NoContent() } // In your bootstrap: // GET /users -> Index // GET /users/:id -> Show // POST /users -> Store // DELETE /users/:id -> Destroy v.Router.Resource("/users", UserController{}).Only("index", "show", "store", "destroy") ``` -------------------------------- ### Implement Custom Service Provider for Stripe Integration Source: https://context7.com/velocitykode/velocity/llms.txt Define a custom service provider to encapsulate third-party integrations like Stripe. This follows a Register, Boot, Shutdown lifecycle. ```go package providers import ( "context" "github.com/velocitykode/velocity/app" stripe "github.com/stripe/stripe-go/v76/client" ) type StripeProvider struct { client *stripe.API } func (p *StripeProvider) Register(s *app.Services) error { key := os.Getenv("STRIPE_SECRET_KEY") p.client = &stripe.API{} p.client.Init(key, nil) return app.RegisterExtension[*stripe.API](s, "stripe", p.client) } func (p *StripeProvider) Boot(s *app.Services) error { // post-registration setup if needed return nil } func (p *StripeProvider) Shutdown(ctx context.Context) error { return nil // clean up if needed } // Register at boot: // v, _ := velocity.New(velocity.WithProviders(&providers.StripeProvider{})) // Retrieve in a handler: // stripeClient, err := app.ExtensionAs[*stripe.API](c.Services(), "stripe") ``` -------------------------------- ### ConfigFromEnv Source: https://context7.com/velocitykode/velocity/llms.txt `ConfigFromEnv` loads all configuration from environment variables (and an optional `.env` file). It is called automatically by `velocity.New()`, but can be called directly to inspect or override config before constructing the app via `velocity.WithConfig`. ```APIDOC ## `velocity.ConfigFromEnv` — Load config from environment `ConfigFromEnv` loads all configuration from environment variables (and an optional `.env` file). It is called automatically by `velocity.New()`, but can be called directly to inspect or override config before constructing the app via `velocity.WithConfig`. ### Usage Example ```go // .env (or real environment variables): // APP_ENV=production // APP_KEY=base64:abc123... // APP_PORT=4000 // DB_CONNECTION=postgres // DB_HOST=localhost // DB_DATABASE=myapp // DB_USERNAME=myapp // DB_PASSWORD=secret // CACHE_DRIVER=redis // REDIS_HOST=127.0.0.1 // QUEUE_DRIVER=redis // MAIL_DRIVER=postmark // MAIL_POSTMARK_TOKEN=tok_xxx package main import ( "fmt" "github.com/velocitykode/velocity" ) func main() { cfg := velocity.ConfigFromEnv() fmt.Println(cfg.Env) // "production" fmt.Println(cfg.DB.Connection) // "postgres" fmt.Println(cfg.Cache.Driver) // "redis" // Pass custom config to New cfg.Port = "9000" v, err := velocity.New(velocity.WithConfig(cfg)) _ = v _ = err } ``` ``` -------------------------------- ### Server-Sent Events Streaming with Context.SSE Source: https://context7.com/velocitykode/velocity/llms.txt Sends named SSE events with JSON data. `PrepareStream` sets headers and clears the write deadline for continuous streaming. ```go v.Router.Get("/events", func(c *router.Context) error { c.PrepareStream() // set SSE headers, clear write deadline ticker := time.NewTicker(2 * time.Second) defer ticker.Stop() for { select { case <-c.Request.Context().Done(): return nil // client disconnected case t := <-ticker.C: if err := c.SSE("tick", map[string]string{ "time": t.Format(time.RFC3339), }); err != nil { return err } } } }) ``` -------------------------------- ### Encrypt and Decrypt Data with AES-256-GCM Source: https://context7.com/velocitykode/velocity/llms.txt Utilize `c.Crypto().Encrypt` and `c.Crypto().Decrypt` for authenticated AES-256-GCM encryption. The service supports zero-downtime key rotation via `CRYPTO_OLD_KEYS`. ```go // APP_KEY=base64:abc123... (generate with: vel key:generate) // CRYPTO_CIPHER=AES-256-GCM // CRYPTO_OLD_KEYS=base64:oldkey1,base64:oldkey2 (key rotation) v.Router.Post("/tokens", func(c *router.Context) error { plaintext := "sensitive-user-token-abc123" // Encrypt encrypted, err := c.Crypto().Encrypt(plaintext) if err != nil { return err } // encrypted = "v1:base64encodedciphertext..." // Decrypt decrypted, err := c.Crypto().Decrypt(encrypted) if err != nil { return err } return c.JSON(200, map[string]string{ "original": plaintext, "encrypted": encrypted, "decrypted": decrypted, }) }) ``` -------------------------------- ### Create a New Branch Source: https://github.com/velocitykode/velocity/blob/main/CONTRIBUTING.md Branching strategy for new features or bug fixes. Ensure your branch is created from the main branch. ```bash git checkout -b feature/my-new-feature # or git checkout -b fix/issue-description ```