Initial commit
This commit is contained in:
190
skills/implementing-features/languages/GENERIC.md
Normal file
190
skills/implementing-features/languages/GENERIC.md
Normal file
@@ -0,0 +1,190 @@
|
||||
# Generic Language Quality Standards
|
||||
|
||||
**Load this file when:** Implementing in languages without specific quality standards (PHP, Ruby, C++, C#, etc.)
|
||||
|
||||
## General Quality Gates
|
||||
|
||||
```yaml
|
||||
Syntax & Structure:
|
||||
- Valid syntax (runs without parse errors)
|
||||
- Consistent indentation (2 or 4 spaces)
|
||||
- Clear variable naming
|
||||
- Functions <= 50 lines (guideline)
|
||||
- Nesting depth <= 3 levels
|
||||
|
||||
Testing:
|
||||
- Unit tests for core functionality
|
||||
- Integration tests for workflows
|
||||
- Edge case coverage
|
||||
- Error path testing
|
||||
- Reasonable coverage (>= 70%)
|
||||
|
||||
Documentation:
|
||||
- README with setup instructions
|
||||
- Function/method documentation
|
||||
- Complex algorithms explained
|
||||
- API documentation (if library)
|
||||
- Usage examples
|
||||
|
||||
Error Handling:
|
||||
- Proper exception/error handling
|
||||
- No swallowed errors
|
||||
- Meaningful error messages
|
||||
- Graceful failure modes
|
||||
- Resource cleanup
|
||||
|
||||
Code Quality:
|
||||
- No code duplication
|
||||
- Clear separation of concerns
|
||||
- Meaningful names
|
||||
- Single responsibility principle
|
||||
- No magic numbers/strings
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Before Declaring Complete:**
|
||||
- [ ] Code runs without errors
|
||||
- [ ] All tests pass
|
||||
- [ ] Documentation complete
|
||||
- [ ] Error handling in place
|
||||
- [ ] No obvious code smells
|
||||
- [ ] Functions reasonably sized
|
||||
- [ ] Clear variable names
|
||||
- [ ] No TODO comments left
|
||||
- [ ] Resources properly managed
|
||||
- [ ] Code reviewed for clarity
|
||||
|
||||
## SOLID Principles
|
||||
|
||||
**Apply regardless of language:**
|
||||
|
||||
```yaml
|
||||
Single Responsibility:
|
||||
- Each class/module has one reason to change
|
||||
- Clear, focused purpose
|
||||
- Avoid "god objects"
|
||||
|
||||
Open/Closed:
|
||||
- Open for extension, closed for modification
|
||||
- Use interfaces/traits for extensibility
|
||||
- Avoid modifying working code
|
||||
|
||||
Liskov Substitution:
|
||||
- Subtypes must be substitutable for base types
|
||||
- Honor contracts in inheritance
|
||||
- Avoid breaking parent behavior
|
||||
|
||||
Interface Segregation:
|
||||
- Many specific interfaces > one general interface
|
||||
- Clients shouldn't depend on unused methods
|
||||
- Keep interfaces focused
|
||||
|
||||
Dependency Inversion:
|
||||
- Depend on abstractions, not concretions
|
||||
- High-level modules independent of low-level
|
||||
- Use dependency injection
|
||||
```
|
||||
|
||||
## Code Smell Detection
|
||||
|
||||
**Watch for these issues:**
|
||||
|
||||
```yaml
|
||||
Long Methods:
|
||||
- Threshold: > 50 lines
|
||||
- Action: Extract smaller methods
|
||||
- Tool: Refactorer agent
|
||||
|
||||
Deep Nesting:
|
||||
- Threshold: > 3 levels
|
||||
- Action: Flatten with early returns
|
||||
- Tool: Refactorer agent
|
||||
|
||||
Duplicate Code:
|
||||
- Detection: Similar code blocks
|
||||
- Action: Extract to shared function
|
||||
- Tool: Refactorer agent
|
||||
|
||||
Large Classes:
|
||||
- Threshold: > 300 lines
|
||||
- Action: Split responsibilities
|
||||
- Tool: Architect + Refactorer agents
|
||||
|
||||
Magic Numbers:
|
||||
- Detection: Unexplained constants
|
||||
- Action: Named constants
|
||||
- Tool: Implementer agent
|
||||
|
||||
Poor Naming:
|
||||
- Detection: Unclear variable names
|
||||
- Action: Rename to be descriptive
|
||||
- Tool: Refactorer agent
|
||||
```
|
||||
|
||||
## Example Quality Pattern
|
||||
|
||||
**Pseudocode showing good practices:**
|
||||
|
||||
```
|
||||
// Good: Clear function with single responsibility
|
||||
function loadConfiguration(filePath: string): Config {
|
||||
// Early validation
|
||||
if (!fileExists(filePath)) {
|
||||
throw FileNotFoundError("Config not found: " + filePath)
|
||||
}
|
||||
|
||||
try {
|
||||
// Clear steps
|
||||
content = readFile(filePath)
|
||||
config = parseYAML(content)
|
||||
validateConfig(config)
|
||||
return config
|
||||
} catch (error) {
|
||||
// Proper error context
|
||||
throw ConfigError("Failed to load config from " + filePath, error)
|
||||
}
|
||||
}
|
||||
|
||||
// Good: Named constants instead of magic numbers
|
||||
const MAX_RETRY_ATTEMPTS = 3
|
||||
const TIMEOUT_MS = 5000
|
||||
|
||||
// Good: Early returns instead of deep nesting
|
||||
function processUser(user: User): Result {
|
||||
if (!user.isActive) {
|
||||
return Result.error("User not active")
|
||||
}
|
||||
|
||||
if (!user.hasPermission) {
|
||||
return Result.error("Insufficient permissions")
|
||||
}
|
||||
|
||||
if (!user.isVerified) {
|
||||
return Result.error("User not verified")
|
||||
}
|
||||
|
||||
// Main logic only runs if all checks pass
|
||||
return Result.success(doProcessing(user))
|
||||
}
|
||||
```
|
||||
|
||||
## Language-Specific Commands
|
||||
|
||||
**Find and use the standard tools for your language:**
|
||||
|
||||
```yaml
|
||||
Python: ruff, pytest, mypy
|
||||
Rust: cargo clippy, cargo test, cargo fmt
|
||||
JavaScript/TypeScript: eslint, prettier, jest/vitest
|
||||
Go: golangci-lint, go test, gofmt
|
||||
Java: checkstyle, junit, maven/gradle
|
||||
C#: dotnet format, xunit, roslyn analyzers
|
||||
Ruby: rubocop, rspec, yard
|
||||
PHP: phpcs, phpunit, psalm/phpstan
|
||||
C++: clang-tidy, gtest, clang-format
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Generic quality standards applicable across programming languages*
|
||||
162
skills/implementing-features/languages/GO.md
Normal file
162
skills/implementing-features/languages/GO.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# Go Quality Standards
|
||||
|
||||
**Load this file when:** Implementing features in Go projects
|
||||
|
||||
## Validation Commands
|
||||
|
||||
```bash
|
||||
# Linting
|
||||
golangci-lint run
|
||||
|
||||
# Formatting
|
||||
gofmt -w .
|
||||
# OR
|
||||
go fmt ./...
|
||||
|
||||
# Tests
|
||||
go test ./...
|
||||
|
||||
# Coverage
|
||||
go test -cover ./...
|
||||
|
||||
# Race Detection
|
||||
go test -race ./...
|
||||
|
||||
# Full Validation Pipeline
|
||||
gofmt -w . && golangci-lint run && go test ./...
|
||||
```
|
||||
|
||||
## Required Standards
|
||||
|
||||
```yaml
|
||||
Code Style:
|
||||
- Follow: Effective Go guidelines
|
||||
- Formatting: gofmt (automatic)
|
||||
- Naming: MixedCaps, not snake_case
|
||||
- Package names: Short, concise, lowercase
|
||||
|
||||
Testing:
|
||||
- Framework: Built-in testing package
|
||||
- Coverage: >= 75%
|
||||
- Test files: *_test.go
|
||||
- Table-driven tests: Prefer for multiple cases
|
||||
- Benchmarks: Include for performance-critical code
|
||||
|
||||
Documentation:
|
||||
- Package: Package-level doc comment
|
||||
- Exported: All exported items documented
|
||||
- Examples: Provide examples for complex APIs
|
||||
- README: Clear usage instructions
|
||||
|
||||
Error Handling:
|
||||
- Return errors, don't panic
|
||||
- Use errors.New or fmt.Errorf
|
||||
- Wrap errors with context (errors.Wrap)
|
||||
- Check all errors explicitly
|
||||
- No ignored errors (use _ = explicitly)
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Before Declaring Complete:**
|
||||
- [ ] Code formatted (`gofmt` or `go fmt`)
|
||||
- [ ] No linting issues (`golangci-lint run`)
|
||||
- [ ] All tests pass (`go test ./...`)
|
||||
- [ ] No race conditions (`go test -race ./...`)
|
||||
- [ ] Test coverage >= 75%
|
||||
- [ ] All exported items documented
|
||||
- [ ] All errors checked explicitly
|
||||
- [ ] No panics in library code
|
||||
- [ ] Proper error wrapping with context
|
||||
- [ ] Resource cleanup with defer
|
||||
|
||||
## Example Quality Pattern
|
||||
|
||||
```go
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
// Config represents the application configuration.
|
||||
type Config struct {
|
||||
APIKey string `yaml:"api_key"`
|
||||
Timeout int `yaml:"timeout"`
|
||||
}
|
||||
|
||||
// LoadConfig loads configuration from a YAML file.
|
||||
//
|
||||
// It returns an error if the file doesn't exist or contains invalid YAML.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// config, err := LoadConfig("config.yaml")
|
||||
// if err != nil {
|
||||
// log.Fatal(err)
|
||||
// }
|
||||
func LoadConfig(path string) (*Config, error) {
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read config file %s: %w", path, err)
|
||||
}
|
||||
|
||||
var config Config
|
||||
if err := yaml.Unmarshal(data, &config); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse YAML in %s: %w", path, err)
|
||||
}
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
```
|
||||
|
||||
**Table-Driven Test Example:**
|
||||
```go
|
||||
func TestLoadConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
path string
|
||||
want *Config
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid config",
|
||||
path: "testdata/valid.yaml",
|
||||
want: &Config{APIKey: "test-key", Timeout: 30},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "missing file",
|
||||
path: "testdata/missing.yaml",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid yaml",
|
||||
path: "testdata/invalid.yaml",
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := LoadConfig(tt.path)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("LoadConfig() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("LoadConfig() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Go-specific quality standards for production-ready code*
|
||||
154
skills/implementing-features/languages/JAVASCRIPT.md
Normal file
154
skills/implementing-features/languages/JAVASCRIPT.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# JavaScript/TypeScript Quality Standards
|
||||
|
||||
**Load this file when:** Implementing features in JavaScript or TypeScript projects
|
||||
|
||||
## Validation Commands
|
||||
|
||||
**JavaScript:**
|
||||
```bash
|
||||
# Linting
|
||||
npx eslint . --fix
|
||||
|
||||
# Formatting
|
||||
npx prettier --write .
|
||||
|
||||
# Tests
|
||||
npm test
|
||||
|
||||
# Full Validation Pipeline
|
||||
npx eslint . && npx prettier --check . && npm test
|
||||
```
|
||||
|
||||
**TypeScript:**
|
||||
```bash
|
||||
# Linting
|
||||
npx eslint . --fix
|
||||
|
||||
# Formatting
|
||||
npx prettier --write .
|
||||
|
||||
# Type Checking
|
||||
npx tsc --noEmit
|
||||
|
||||
# Tests
|
||||
npm test
|
||||
|
||||
# Full Validation Pipeline
|
||||
npx eslint . && npx prettier --check . && npx tsc --noEmit && npm test
|
||||
```
|
||||
|
||||
## Required Standards
|
||||
|
||||
```yaml
|
||||
Code Style:
|
||||
- Line length: 100-120 characters
|
||||
- Semicolons: Consistent (prefer with)
|
||||
- Quotes: Single or double (consistent)
|
||||
- Trailing commas: Always in multiline
|
||||
|
||||
Testing:
|
||||
- Framework: Jest, Mocha, or Vitest
|
||||
- Coverage: >= 80%
|
||||
- Test files: *.test.js, *.spec.js
|
||||
- Mocking: Prefer dependency injection
|
||||
- Async: Use async/await, not callbacks
|
||||
|
||||
Documentation:
|
||||
- JSDoc for all exported functions
|
||||
- README for packages
|
||||
- Type definitions (TypeScript or JSDoc)
|
||||
- API documentation for libraries
|
||||
|
||||
TypeScript Specific:
|
||||
- Strict mode enabled
|
||||
- No 'any' types (use 'unknown' if needed)
|
||||
- Proper interface/type definitions
|
||||
- Generic types where appropriate
|
||||
- Discriminated unions for state
|
||||
|
||||
Error Handling:
|
||||
- Try/catch for async operations
|
||||
- Error boundaries (React)
|
||||
- Proper promise handling
|
||||
- No unhandled promise rejections
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Before Declaring Complete:**
|
||||
- [ ] No linting errors (`eslint .`)
|
||||
- [ ] Code formatted (`prettier --check .`)
|
||||
- [ ] Type checking passes (TS: `tsc --noEmit`)
|
||||
- [ ] All tests pass (`npm test`)
|
||||
- [ ] Test coverage >= 80%
|
||||
- [ ] No 'any' types (TypeScript)
|
||||
- [ ] All exported functions have JSDoc
|
||||
- [ ] Async operations properly handled
|
||||
- [ ] Error boundaries implemented (React)
|
||||
- [ ] No console.log in production code
|
||||
|
||||
## Example Quality Pattern
|
||||
|
||||
**TypeScript:**
|
||||
```typescript
|
||||
/**
|
||||
* Load configuration from YAML file.
|
||||
*
|
||||
* @param configPath - Path to configuration file
|
||||
* @returns Parsed configuration object
|
||||
* @throws {Error} If file doesn't exist or YAML is invalid
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const config = await loadConfig('./config.yaml');
|
||||
* console.log(config.apiKey);
|
||||
* ```
|
||||
*/
|
||||
export async function loadConfig(configPath: string): Promise<Config> {
|
||||
if (!fs.existsSync(configPath)) {
|
||||
throw new Error(`Config not found: ${configPath}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const contents = await fs.promises.readFile(configPath, 'utf-8');
|
||||
const config = yaml.parse(contents) as Config;
|
||||
return config;
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid YAML in ${configPath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**JavaScript with JSDoc:**
|
||||
```javascript
|
||||
/**
|
||||
* @typedef {Object} Config
|
||||
* @property {string} apiKey - API key for service
|
||||
* @property {number} timeout - Request timeout in ms
|
||||
*/
|
||||
|
||||
/**
|
||||
* Load configuration from YAML file.
|
||||
*
|
||||
* @param {string} configPath - Path to configuration file
|
||||
* @returns {Promise<Config>} Parsed configuration object
|
||||
* @throws {Error} If file doesn't exist or YAML is invalid
|
||||
*/
|
||||
export async function loadConfig(configPath) {
|
||||
if (!fs.existsSync(configPath)) {
|
||||
throw new Error(`Config not found: ${configPath}`);
|
||||
}
|
||||
|
||||
try {
|
||||
const contents = await fs.promises.readFile(configPath, 'utf-8');
|
||||
const config = yaml.parse(contents);
|
||||
return config;
|
||||
} catch (error) {
|
||||
throw new Error(`Invalid YAML in ${configPath}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*JavaScript/TypeScript-specific quality standards for production-ready code*
|
||||
101
skills/implementing-features/languages/PYTHON.md
Normal file
101
skills/implementing-features/languages/PYTHON.md
Normal file
@@ -0,0 +1,101 @@
|
||||
# Python Quality Standards
|
||||
|
||||
**Load this file when:** Implementing features in Python projects
|
||||
|
||||
## Validation Commands
|
||||
|
||||
```bash
|
||||
# Linting
|
||||
ruff check . --fix
|
||||
|
||||
# Formatting
|
||||
ruff format .
|
||||
|
||||
# Tests
|
||||
pytest -v
|
||||
|
||||
# Type Checking
|
||||
mypy . --ignore-missing-imports
|
||||
|
||||
# Coverage
|
||||
pytest --cov --cov-report=html
|
||||
|
||||
# Full Validation Pipeline
|
||||
ruff check . && ruff format . && mypy . && pytest
|
||||
```
|
||||
|
||||
## Required Standards
|
||||
|
||||
```yaml
|
||||
Code Style:
|
||||
- Line length: 120 characters (configurable)
|
||||
- Imports: Sorted with isort style
|
||||
- Docstrings: Google or NumPy style
|
||||
- Type hints: Everywhere (functions, methods, variables)
|
||||
|
||||
Testing:
|
||||
- Framework: pytest
|
||||
- Coverage: >= 80%
|
||||
- Test files: test_*.py or *_test.py
|
||||
- Fixtures: Prefer pytest fixtures over setup/teardown
|
||||
- Assertions: Use pytest assertions, not unittest
|
||||
|
||||
Documentation:
|
||||
- All modules: Docstring with purpose
|
||||
- All classes: Docstring with attributes
|
||||
- All functions: Docstring with args, returns, raises
|
||||
- Complex logic: Inline comments for clarity
|
||||
|
||||
Error Handling:
|
||||
- Use specific exceptions (not bare except)
|
||||
- Custom exceptions for domain errors
|
||||
- Proper exception chaining
|
||||
- Clean resource management (context managers)
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Before Declaring Complete:**
|
||||
- [ ] All functions have type hints
|
||||
- [ ] All functions have docstrings (Google/NumPy style)
|
||||
- [ ] No linting errors (`ruff check .`)
|
||||
- [ ] Code formatted consistently (`ruff format .`)
|
||||
- [ ] Type checking passes (`mypy .`)
|
||||
- [ ] All tests pass (`pytest`)
|
||||
- [ ] Test coverage >= 80%
|
||||
- [ ] No bare except clauses
|
||||
- [ ] Proper exception handling
|
||||
- [ ] Resources properly managed
|
||||
|
||||
## Example Quality Pattern
|
||||
|
||||
```python
|
||||
from typing import Optional
|
||||
from pathlib import Path
|
||||
|
||||
def load_config(config_path: Path) -> dict[str, any]:
|
||||
"""Load configuration from YAML file.
|
||||
|
||||
Args:
|
||||
config_path: Path to configuration file
|
||||
|
||||
Returns:
|
||||
Dictionary containing configuration values
|
||||
|
||||
Raises:
|
||||
FileNotFoundError: If config file doesn't exist
|
||||
ValueError: If config file is invalid YAML
|
||||
"""
|
||||
if not config_path.exists():
|
||||
raise FileNotFoundError(f"Config not found: {config_path}")
|
||||
|
||||
try:
|
||||
with config_path.open() as f:
|
||||
return yaml.safe_load(f)
|
||||
except yaml.YAMLError as e:
|
||||
raise ValueError(f"Invalid YAML in {config_path}") from e
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Python-specific quality standards for production-ready code*
|
||||
120
skills/implementing-features/languages/RUST.md
Normal file
120
skills/implementing-features/languages/RUST.md
Normal file
@@ -0,0 +1,120 @@
|
||||
# Rust Quality Standards
|
||||
|
||||
**Load this file when:** Implementing features in Rust projects
|
||||
|
||||
## Validation Commands
|
||||
|
||||
```bash
|
||||
# Linting
|
||||
cargo clippy -- -D warnings
|
||||
|
||||
# Formatting
|
||||
cargo fmt
|
||||
|
||||
# Tests
|
||||
cargo test
|
||||
|
||||
# Type Checking (implicit)
|
||||
cargo check
|
||||
|
||||
# Documentation
|
||||
cargo doc --no-deps --open
|
||||
|
||||
# Full Validation Pipeline
|
||||
cargo clippy -- -D warnings && cargo fmt --check && cargo test
|
||||
```
|
||||
|
||||
## Required Standards
|
||||
|
||||
```yaml
|
||||
Code Style:
|
||||
- Follow: Rust API guidelines
|
||||
- Formatting: rustfmt (automatic)
|
||||
- Naming: snake_case for functions, PascalCase for types
|
||||
- Modules: Clear separation of concerns
|
||||
|
||||
Testing:
|
||||
- Framework: Built-in test framework
|
||||
- Coverage: >= 75%
|
||||
- Unit tests: In same file with #[cfg(test)]
|
||||
- Integration tests: In tests/ directory
|
||||
- Doc tests: In documentation examples
|
||||
|
||||
Documentation:
|
||||
- All public items: /// documentation
|
||||
- Modules: //! module-level docs
|
||||
- Examples: Working examples in docs
|
||||
- Safety: Document unsafe blocks thoroughly
|
||||
|
||||
Error Handling:
|
||||
- Use Result<T, E> for fallible operations
|
||||
- Use Option<T> for optional values
|
||||
- No .unwrap() in production code
|
||||
- Custom error types with thiserror or anyhow
|
||||
- Proper error context with context/wrap_err
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
**Before Declaring Complete:**
|
||||
- [ ] No clippy warnings (`cargo clippy -- -D warnings`)
|
||||
- [ ] Code formatted (`cargo fmt --check`)
|
||||
- [ ] All tests pass (`cargo test`)
|
||||
- [ ] No unwrap() calls in production code
|
||||
- [ ] Result<T, E> used for all fallible operations
|
||||
- [ ] All public items documented
|
||||
- [ ] Examples in documentation tested
|
||||
- [ ] Unsafe blocks documented with safety comments
|
||||
- [ ] Proper error types defined
|
||||
- [ ] Resource cleanup handled (Drop trait if needed)
|
||||
|
||||
## Example Quality Pattern
|
||||
|
||||
```rust
|
||||
use thiserror::Error;
|
||||
use std::path::Path;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ConfigError {
|
||||
#[error("Config file not found: {0}")]
|
||||
NotFound(String),
|
||||
#[error("Invalid YAML: {0}")]
|
||||
InvalidYaml(#[from] serde_yaml::Error),
|
||||
}
|
||||
|
||||
/// Load configuration from YAML file.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `path` - Path to configuration file
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// Returns the parsed configuration or an error.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `ConfigError::NotFound` if file doesn't exist.
|
||||
/// Returns `ConfigError::InvalidYaml` if parsing fails.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let config = load_config(Path::new("config.yaml"))?;
|
||||
/// ```
|
||||
pub fn load_config(path: &Path) -> Result<Config, ConfigError> {
|
||||
if !path.exists() {
|
||||
return Err(ConfigError::NotFound(path.display().to_string()));
|
||||
}
|
||||
|
||||
let contents = std::fs::read_to_string(path)
|
||||
.map_err(|e| ConfigError::InvalidYaml(e.into()))?;
|
||||
|
||||
let config: Config = serde_yaml::from_str(&contents)?;
|
||||
Ok(config)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Rust-specific quality standards for production-ready code*
|
||||
Reference in New Issue
Block a user