feat: improve resource routing API and add comprehensive quality standards
BREAKING CHANGES:
- Renamed HandleGET -> MemberGET for member-level routes
- Renamed HandlePOST -> MemberPOST for member-level routes
- Renamed HandlePUT -> MemberPUT for member-level routes
- Renamed HandlePATCH -> MemberPATCH for member-level routes
- Renamed HandleDELETE -> MemberDELETE for member-level routes
New Features:
- Added collection-level route methods: GET, POST, PUT, PATCH, DELETE
- Clear distinction between collection (/pattern/action) and member (/pattern/{id}/action) routes
- Comprehensive documentation (README, CONTRIBUTING, QUICKSTART, DOCS)
- Development tooling (Makefile, check.sh script)
- AI coding assistant guidelines (.cursorrules)
- GitHub Actions CI/CD pipeline
- golangci-lint configuration
Code Quality:
- Optimized struct field alignment for better memory usage
- All code passes go vet, staticcheck, and fieldalignment
- All tests pass with race detector
- Go 1.25+ requirement enforced
Documentation:
- Complete README rewrite with examples
- CONTRIBUTING.md with development guidelines
- QUICKSTART.md for new users
- CHANGELOG.md with version history
- SUMMARY.md documenting all changes
- DOCS.md as documentation index
This commit is contained in:
294
.cursorrules
Normal file
294
.cursorrules
Normal file
@@ -0,0 +1,294 @@
|
||||
# Mux Project - AI Coding Assistant Rules
|
||||
|
||||
## Project Overview
|
||||
This is a lightweight HTTP router for Go that wraps the standard library's http.ServeMux.
|
||||
The project emphasizes simplicity, performance, and zero external dependencies.
|
||||
|
||||
## Language and Version Requirements
|
||||
- **Language**: Go
|
||||
- **Minimum Version**: Go 1.25+
|
||||
- **Standard Library Only**: No external dependencies except for optional middleware examples
|
||||
|
||||
## Code Quality Standards
|
||||
|
||||
### Mandatory Checks
|
||||
All code MUST pass these checks before committing:
|
||||
|
||||
1. **go vet**: `go vet ./...`
|
||||
- Catches common mistakes and suspicious constructs
|
||||
- Must pass with zero warnings
|
||||
|
||||
2. **staticcheck**: `staticcheck ./...`
|
||||
- Advanced static analysis
|
||||
- Catches bugs, inefficiencies, and style issues
|
||||
- Must pass with zero warnings
|
||||
|
||||
3. **fieldalignment**: `go vet -vettool=$(which fieldalignment) ./...`
|
||||
- Ensures optimal struct field ordering
|
||||
- Minimizes memory usage through proper alignment
|
||||
- Apply fixes when suggested
|
||||
|
||||
4. **Tests with Race Detection**: `go test -race ./...`
|
||||
- All tests must pass
|
||||
- No race conditions allowed
|
||||
|
||||
### Running All Checks
|
||||
```bash
|
||||
go vet ./...
|
||||
staticcheck ./...
|
||||
go test -race ./...
|
||||
go vet -vettool=$(which fieldalignment) ./...
|
||||
```
|
||||
|
||||
## Code Style and Conventions
|
||||
|
||||
### General Principles
|
||||
- **Simplicity First**: Prefer clear, straightforward code over clever solutions
|
||||
- **Zero Allocations**: Optimize hot paths to minimize heap allocations
|
||||
- **Standard Library**: Use only Go standard library unless absolutely necessary
|
||||
- **Fail Fast**: Use panics for programmer errors, return errors for runtime issues
|
||||
- **No Reflection**: Avoid runtime reflection for performance reasons
|
||||
|
||||
### Naming Conventions
|
||||
- Use `MixedCaps` or `mixedCaps` (not snake_case)
|
||||
- Short names for local variables (i, err, w, r, etc.)
|
||||
- Descriptive names for exported identifiers
|
||||
- Avoid package name stuttering (mux.Mux, not mux.MuxRouter)
|
||||
- Use conventional names: `m` for Mux, `res` for Resource, `w` for ResponseWriter, `r` for Request
|
||||
|
||||
### Function and Method Design
|
||||
- Keep functions small and focused (prefer < 50 lines)
|
||||
- One level of abstraction per function
|
||||
- Early returns to reduce nesting
|
||||
- Validate inputs early (fail fast)
|
||||
|
||||
### Error Handling
|
||||
- Never ignore errors (no `_` for error returns unless documented why)
|
||||
- Use `panic()` for programmer errors (nil checks, invalid configs)
|
||||
- Return errors for runtime failures
|
||||
- Provide context in error messages
|
||||
- Use standard error wrapping: `fmt.Errorf("context: %w", err)`
|
||||
|
||||
### Comments and Documentation
|
||||
- All exported functions, types, and methods MUST have comments
|
||||
- Comments start with the name being described
|
||||
- Use complete sentences with proper punctuation
|
||||
- Explain "why" not "what" for complex logic
|
||||
- Update comments when changing code
|
||||
|
||||
Example:
|
||||
```go
|
||||
// New creates and returns a new Mux router instance with an empty route table
|
||||
// and no middleware configured.
|
||||
func New() *Mux {
|
||||
return &Mux{
|
||||
mux: http.NewServeMux(),
|
||||
routes: new(RouteList),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Struct Field Ordering
|
||||
Always order struct fields by size (largest to smallest) for optimal memory alignment:
|
||||
|
||||
```go
|
||||
// Good - optimally aligned
|
||||
type Resource struct {
|
||||
mux *http.ServeMux // 8 bytes (pointer)
|
||||
pattern string // 16 bytes (string header)
|
||||
middlewares []func(http.Handler) http.Handler // 24 bytes (slice header)
|
||||
routes *RouteList // 8 bytes (pointer)
|
||||
}
|
||||
|
||||
// Bad - poor alignment
|
||||
type Resource struct {
|
||||
pattern string
|
||||
mux *http.ServeMux
|
||||
routes *RouteList
|
||||
middlewares []func(http.Handler) http.Handler
|
||||
}
|
||||
```
|
||||
|
||||
## Project-Specific Patterns
|
||||
|
||||
### Middleware Signature
|
||||
All middleware must follow the standard signature:
|
||||
```go
|
||||
func middleware(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// pre-processing
|
||||
next.ServeHTTP(w, r)
|
||||
// post-processing
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### Nil Checks
|
||||
All public methods must check for nil receivers and panic with clear messages:
|
||||
```go
|
||||
func (m *Mux) Use(h ...func(http.Handler) http.Handler) {
|
||||
if m == nil {
|
||||
panic("mux: Use() called on nil")
|
||||
}
|
||||
m.middlewares = append(m.middlewares, h...)
|
||||
}
|
||||
```
|
||||
|
||||
### Route Pattern Validation
|
||||
- Always validate pattern strings are non-empty
|
||||
- Ensure patterns start with "/"
|
||||
- Add prefix "/" if missing (normalize patterns)
|
||||
|
||||
### Resource Routing Conventions
|
||||
- **Collection routes**: Operate on `/pattern/action` (use `POST`, `GET`, etc.)
|
||||
- **Member routes**: Operate on `/pattern/{id}/action` (use `MemberPOST`, `MemberGET`, etc.)
|
||||
- Always use `{id}` as the parameter name for resource identifiers
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Test Structure
|
||||
Use Arrange-Act-Assert pattern:
|
||||
```go
|
||||
func TestFeature(t *testing.T) {
|
||||
// Arrange
|
||||
m := mux.New()
|
||||
|
||||
// Act
|
||||
m.GET("/test", handler)
|
||||
|
||||
// Assert
|
||||
if got != want {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Test Coverage
|
||||
- All exported functions must have tests
|
||||
- Test happy paths and error cases
|
||||
- Test edge cases and boundary conditions
|
||||
- Include table-driven tests for multiple scenarios
|
||||
- Aim for >80% code coverage
|
||||
|
||||
### Benchmarks
|
||||
Include benchmarks for performance-critical code:
|
||||
```go
|
||||
func BenchmarkFeature(b *testing.B) {
|
||||
// setup
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
// code to benchmark
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Guidelines
|
||||
|
||||
### Memory Management
|
||||
- Reuse buffers where possible (sync.Pool for hot paths)
|
||||
- Avoid unnecessary allocations in request handlers
|
||||
- Use string builders for concatenation
|
||||
- Pre-allocate slices with known capacity
|
||||
|
||||
### Concurrency
|
||||
- All exported methods must be safe for concurrent use
|
||||
- Use atomic operations for simple flags (e.g., IsShuttingDown)
|
||||
- Document any concurrency requirements or limitations
|
||||
- Test concurrent access with `-race` flag
|
||||
|
||||
## Documentation Standards
|
||||
|
||||
### README Updates
|
||||
When adding features:
|
||||
- Add to Table of Contents if new section
|
||||
- Provide working code examples
|
||||
- Show both basic and advanced usage
|
||||
- Update Quick Start if core API changes
|
||||
|
||||
### Code Examples
|
||||
- Must be runnable without modification
|
||||
- Use realistic names and scenarios
|
||||
- Include error handling
|
||||
- Show best practices
|
||||
|
||||
## Common Patterns in This Project
|
||||
|
||||
### Handler Registration
|
||||
```go
|
||||
// Pattern: method + " " + pattern
|
||||
path := fmt.Sprintf("%s %s", method, pattern)
|
||||
m.mux.Handle(path, stack(h, m.middlewares))
|
||||
m.routes.Add(path)
|
||||
```
|
||||
|
||||
### Middleware Stacking
|
||||
```go
|
||||
// Stack middleware from slice, innermost handler first
|
||||
handler := h
|
||||
for i := len(middlewares) - 1; i >= 0; i-- {
|
||||
handler = middlewares[i](handler)
|
||||
}
|
||||
```
|
||||
|
||||
### Suffix Path Building
|
||||
```go
|
||||
// Always ensure single "/" between components
|
||||
if !strings.HasSuffix(base, "/") {
|
||||
base += "/"
|
||||
}
|
||||
path := base + suffix
|
||||
```
|
||||
|
||||
## Anti-Patterns to Avoid
|
||||
|
||||
❌ **Don't** use global variables
|
||||
❌ **Don't** ignore errors without explicit comment
|
||||
❌ **Don't** use naked returns in long functions
|
||||
❌ **Don't** add external dependencies
|
||||
❌ **Don't** use reflection
|
||||
❌ **Don't** create goroutines without cleanup
|
||||
❌ **Don't** use `interface{}` (use `any` in Go 1.18+)
|
||||
❌ **Don't** allocate in hot paths unnecessarily
|
||||
❌ **Don't** panic for runtime errors (use error returns)
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
Use conventional commits:
|
||||
- `feat:` - New feature
|
||||
- `fix:` - Bug fix
|
||||
- `docs:` - Documentation changes
|
||||
- `test:` - Test additions/modifications
|
||||
- `refactor:` - Code refactoring
|
||||
- `perf:` - Performance improvements
|
||||
- `chore:` - Maintenance tasks
|
||||
|
||||
Example: `feat: add MemberPOST and MemberGET methods to Resource`
|
||||
|
||||
## AI Assistant Guidelines
|
||||
|
||||
When generating code:
|
||||
1. Run quality checks mentally (vet, staticcheck, fieldalignment)
|
||||
2. Ensure proper nil checks on all methods
|
||||
3. Add comments for all exported items
|
||||
4. Follow existing naming patterns
|
||||
5. Maintain zero external dependencies
|
||||
6. Optimize for performance (zero allocs in hot paths)
|
||||
7. Write concurrent-safe code
|
||||
8. Include tests with new features
|
||||
9. Update README.md if adding public APIs
|
||||
10. Use Go 1.25+ features when appropriate
|
||||
|
||||
## Questions to Ask Before Coding
|
||||
|
||||
1. Does this maintain zero external dependencies?
|
||||
2. Is this the simplest solution?
|
||||
3. Will this pass go vet, staticcheck, and fieldalignment?
|
||||
4. Is this safe for concurrent use?
|
||||
5. Does this follow existing patterns?
|
||||
6. Are all exported items documented?
|
||||
7. Have I added tests?
|
||||
8. Can this be optimized to reduce allocations?
|
||||
|
||||
---
|
||||
|
||||
Remember: Simplicity, performance, and maintainability are the core values of this project.
|
||||
Reference in New Issue
Block a user