Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 14 additions & 8 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,23 @@ version: "2"

run:
timeout: 5m
go: "1.25"
go: "1.21"

linters:
enable:
# Safety and correctness (enabled by default)
- govet
- ineffassign
disable:
- staticcheck
- errcheck
- ineffassign
- unused
- staticcheck

formatters:
enable:
- gofmt

# Code quality
- misspell

# Documentation (strict for library)
- revive
disable:
- exhaustive
- exhaustruct
- varnamelen
64 changes: 64 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,68 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2025-12-16

### Added - Library Export (Feature 002)

#### Core Generation API
- **Generator struct**: Provides the main interface for programmatic template generation
- `NewGenerator(engine Engine) (*Generator, error)` - Creates a new generator with a template engine
- `Generate(ctx context.Context, templatePath string, variables map[string]interface{}, outputPath string) error` - Generates projects from templates
- `GetEngine() Engine` - Retrieves the configured engine
- Context cancellation support for graceful timeout/cancellation handling
- Full input validation (empty paths, invalid variable names)
- Path traversal prevention for security
- Binary file preservation during generation
- Thread-safe implementation with RWMutex protection

#### Registry Management API
- **Registry struct**: Template registry management with XDG compliance
- `NewRegistry() (*Registry, error)` - Uses default XDG location (~/.local/share/ason/registry.toml)
- `NewRegistryAt(registryPath string) (*Registry, error)` - Custom registry path
- `Register(name, templatePath, description string) error` - Register templates
- `List() ([]TemplateInfo, error)` - List all registered templates (alphabetically sorted)
- `Remove(name string) error` - Remove templates (idempotent)
- **TemplateInfo struct**: Template metadata (Name, Path, Created, Description)
- Atomic TOML persistence (temp file + rename pattern)
- Thread-safe concurrent operations (multiple concurrent reads, serialized writes)
- Proper XDG Base Directory compliance

#### Engine Interface
- **Engine interface**: Pluggable template engine support
- `Render(template string, context map[string]interface{}) (string, error)` - Render template strings
- `RenderFile(filePath string, context map[string]interface{}) (string, error)` - Render template files
- **NewDefaultEngine()**: Pongo2 template engine implementation
- **RenderWithEngine()**: Context-aware rendering helper function
- Comprehensive engine interface documentation in `docs/api/engine_interface.md`
- Custom engine implementation guidelines

#### Error Types
- **TemplateNotFoundError**: When template path doesn't exist
- **InvalidPathError**: For path traversal or invalid paths
- **VariableValidationError**: For invalid variable names/values
- **GenerationError**: For template rendering failures
- **EngineError**: For engine-specific failures
- All errors support `Unwrap()` for error chaining

#### API Locations
- Public API: `pkg/generator.go`, `pkg/engine.go`, `pkg/registry.go`
- Documentation: `docs/api/engine_interface.md`
- Examples: Included in inline godoc comments

### Improved
- Test infrastructure with proper temporary directory handling
- Fixed .golangci.yml configuration syntax
- Removed duplicate test files, consolidated test suites

### Changed
- **BREAKING (Minor)**: None - fully backward compatible with CLI

### Security
- Input validation for all paths and variable names
- Path traversal prevention checks
- Registry operations are atomic with temporary file pattern

## [0.2.2] - 2025-10-22

### Fixed
Expand All @@ -33,6 +95,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

See git tags for release history.

[0.3.0]: https://github.com/madstone-tech/ason/compare/v0.2.2...v0.3.0
[0.2.2]: https://github.com/madstone-tech/ason/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/madstone-tech/ason/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/madstone-tech/ason/compare/v0.1.0...v0.2.0
[0.1.0]: https://github.com/madstone-tech/ason/releases/tag/v0.1.0
162 changes: 162 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,168 @@ ason new my-template my-project
ason new ./path/to/template my-project
```

## Using Ason as a Library

Ason provides a comprehensive public API for using it as a library in your Go projects.

### Installation

```bash
go get github.com/madstone-tech/ason
```

### Core Features

#### 1. **Generator** - Template Rendering
```go
package main

import (
"context"
"log"
"github.com/madstone-tech/ason/pkg"
)

func main() {
// Create a generator with the default engine
engine := pkg.NewDefaultEngine()
gen, err := pkg.NewGenerator(engine)
if err != nil {
log.Fatal(err)
}

// Generate a project
variables := map[string]interface{}{
"project_name": "my-app",
"author": "Alice",
}

ctx := context.Background()
err = gen.Generate(ctx, "./template", variables, "./output")
if err != nil {
log.Fatal(err)
}
}
```

#### 2. **Registry** - Template Management
```go
package main

import (
"log"
"github.com/madstone-tech/ason/pkg"
)

func main() {
// Use default XDG-compliant registry
reg, err := pkg.NewRegistry()
if err != nil {
log.Fatal(err)
}

// Register a template
err = reg.Register("my-template", "/path/to/template", "My project template")
if err != nil {
log.Fatal(err)
}

// List templates
templates, err := reg.List()
if err != nil {
log.Fatal(err)
}

for _, t := range templates {
println(t.Name, t.Path)
}

// Remove a template
err = reg.Remove("my-template")
if err != nil {
log.Fatal(err)
}
}
```

#### 3. **Custom Engines** - Pluggable Template Engines
```go
package main

import (
"context"
"log"
"github.com/madstone-tech/ason/pkg"
)

type CustomEngine struct{}

func (e *CustomEngine) Render(template string, ctx map[string]interface{}) (string, error) {
// Implement your template rendering logic
return template, nil
}

func (e *CustomEngine) RenderFile(filePath string, ctx map[string]interface{}) (string, error) {
// Implement file rendering
return "", nil
}

func main() {
// Use a custom engine
engine := &CustomEngine{}
gen, err := pkg.NewGenerator(engine)
if err != nil {
log.Fatal(err)
}

variables := map[string]interface{}{}
ctx := context.Background()
err = gen.Generate(ctx, "./template", variables, "./output")
if err != nil {
log.Fatal(err)
}
}
```

### Key Components

- **Generator**: `NewGenerator(engine Engine)` - Create a generator with any engine
- `Generate()` - Render templates with context support
- `GetEngine()` - Retrieve the configured engine

- **Registry**: `NewRegistry()` / `NewRegistryAt(path)` - Manage templates
- `Register()`, `List()`, `Remove()` - Template CRUD operations
- XDG Base Directory compliant storage

- **Engine Interface**: Pluggable template engine system
- `NewDefaultEngine()` - Default Pongo2 implementation
- `RenderWithEngine()` - Context-aware rendering helper
- Implement `Engine` interface for custom engines

### API Documentation

For detailed API documentation, see:
- [Engine Interface Documentation](docs/api/engine_interface.md)
- [GoDoc](https://pkg.go.dev/github.com/madstone-tech/ason)

### Thread Safety

All public types are thread-safe:
- **Generator**: RWMutex-protected for concurrent operations
- **Registry**: Multiple concurrent reads, serialized writes
- **Engine**: Implementation must be thread-safe

### Error Handling

Ason provides specific error types for proper error handling:
- `TemplateNotFoundError` - Template doesn't exist
- `InvalidPathError` - Invalid path (traversal prevention)
- `VariableValidationError` - Invalid variable names/values
- `GenerationError` - Template rendering failed
- `EngineError` - Engine-specific failure

All errors support `Unwrap()` for error chaining.

## Features

- 🪇 **Rhythmic Generation**: Fast, lightweight operation with minimal dependencies
Expand Down
Loading