# Common Patterns for Demo Skills

This file contains common patterns and code snippets for creating demo skills.

## Pattern 1: Data Generation

### Generate JSON from DuckDB

```python
import duckdb
import json
from pathlib import Path

def generate_data(db_path: str, output_path: str) -> None:
    """Generate JSON data from DuckDB database."""
    
    conn = duckdb.connect(db_path)
    
    # Query the database
    query = "SELECT * FROM my_table ORDER BY year"
    data = conn.execute(query).fetchdf().to_dict(orient="records")
    
    conn.close()
    
    # Write to JSON
    output_file = Path(output_path)
    output_file.parent.mkdir(parents=True, exist_ok=True)
    
    with open(output_file, "w") as f:
        json.dump(data, f, indent=2)
    
    print(f"Generated: {output_path}")
```

### Generate mock data

```python
import json
from pathlib import Path

def generate_mock_data(output_path: str) -> None:
    """Generate mock JSON data."""
    
    data = [
        {"year": 2014, "value": 100},
        {"year": 2015, "value": 105},
        {"year": 2016, "value": 110},
        {"year": 2017, "value": 115},
        {"year": 2018, "value": 120},
    ]
    
    output_file = Path(output_path)
    output_file.parent.mkdir(parents=True, exist_ok=True)
    
    with open(output_file, "w") as f:
        json.dump(data, f, indent=2)
    
    print(f"Generated: {output_path}")
```

## Pattern 2: Page Creation

### Create page from template

```python
from pathlib import Path

def create_page(template_path: str, output_path: str) -> None:
    """Create a React page from a template."""
    
    template = Path(template_path)
    output = Path(output_path)
    
    # Read template
    content = template.read_text()
    
    # Create output directory
    output.parent.mkdir(parents=True, exist_ok=True)
    
    # Write page
    output.write_text(content)
    
    print(f"Created: {output_path}")
```

### Create page with dynamic content

```python
from pathlib import Path

def create_page_with_data(template_path: str, output_path: str, data: dict) -> None:
    """Create a React page with dynamic data."""
    
    template = Path(template_path)
    output = Path(output_path)
    
    # Read template
    content = template.read_text()
    
    # Replace placeholders
    for key, value in data.items():
        content = content.replace(f"{{{{ {key} }}}}", str(value))
    
    # Create output directory
    output.parent.mkdir(parents=True, exist_ok=True)
    
    # Write page
    output.write_text(content)
    
    print(f"Created: {output_path}")
```

## Pattern 3: Route Addition

### Add route to App.tsx

```python
from pathlib import Path

def add_route(route_path: str, component_name: str) -> None:
    """Add a route to App.tsx."""
    
    app_path = Path("web/scratch/src/App.tsx")
    
    if not app_path.exists():
        print(f"ERROR: App.tsx not found at {app_path}")
        return False
    
    content = app_path.read_text()
    
    # Check if route already exists
    if f'path="{route_path}"' in content:
        print(f"Route already exists: {route_path}")
        return True
    
    # Add import statement
    import_statement = f'import {component_name} from "./pages/{component_name}";'
    
    # Find the last import statement
    lines = content.split("\n")
    import_idx = 0
    for i, line in enumerate(lines):
        if "import" in line and "from" in line:
            import_idx = i
    
    lines.insert(import_idx + 1, import_statement)
    
    # Add route element
    route_element = f'  <Route path="{route_path}" element={<{component_name} />} />'
    
    # Find the closing Routes tag
    routes_idx = 0
    for i, line in enumerate(lines):
        if "</Routes>" in line:
            routes_idx = i
            break
    
    lines.insert(routes_idx, route_element)
    
    # Write back
    app_path.write_text("\n".join(lines))
    
    print(f"Added route: {route_path}")
    return True
```

### Remove route from App.tsx

```python
from pathlib import Path

def remove_route(route_path: str, component_name: str) -> None:
    """Remove a route from App.tsx."""
    
    app_path = Path("web/scratch/src/App.tsx")
    
    if not app_path.exists():
        print(f"ERROR: App.tsx not found at {app_path}")
        return False
    
    content = app_path.read_text()
    
    # Remove import statement
    import_statement = f'import {component_name} from "./pages/{component_name}";'
    content = content.replace(import_statement, "")
    
    # Remove route element
    route_element = f'  <Route path="{route_path}" element={<{component_name} />} />'
    content = content.replace(route_element, "")
    
    # Write back
    app_path.write_text(content)
    
    print(f"Removed route: {route_path}")
    return True
```

## Pattern 4: Verification

### Verify files exist

```python
from pathlib import Path

def verify_files(file_paths: list) -> bool:
    """Verify that all files exist."""
    
    all_exist = True
    
    for file_path in file_paths:
        path = Path(file_path)
        
        if path.exists():
            print(f"✓ {file_path}")
        else:
            print(f"✗ {file_path} (not found)")
            all_exist = False
    
    return all_exist
```

### Verify page works

```python
from pathlib import Path

def verify_page(page_path: str, data_path: str) -> bool:
    """Verify that a page and its data exist."""
    
    page = Path(page_path)
    data = Path(data_path)
    
    if not page.exists():
        print(f"ERROR: Page not found: {page_path}")
        return False
    
    if not data.exists():
        print(f"ERROR: Data not found: {data_path}")
        return False
    
    print(f"✓ {page_path}")
    print(f"✓ {data_path}")
    return True
```

## Pattern 5: Cleanup

### Remove files

```python
import shutil
from pathlib import Path

def remove_files(file_paths: list) -> None:
    """Remove all files in the list."""
    
    for file_path in file_paths:
        path = Path(file_path)
        
        if path.exists():
            try:
                if path.is_dir():
                    shutil.rmtree(path)
                    print(f"✓ Removed directory: {file_path}")
                else:
                    path.unlink()
                    print(f"✓ Removed file: {file_path}")
            except Exception as e:
                print(f"✗ Failed to remove {file_path}: {e}")
        else:
            print(f"  Already removed: {file_path}")
```

### Remove directory

```python
import shutil
from pathlib import Path

def remove_directory(dir_path: str) -> None:
    """Remove a directory and all its contents."""
    
    path = Path(dir_path)
    
    if path.exists():
        try:
            shutil.rmtree(path)
            print(f"✓ Removed directory: {dir_path}")
        except Exception as e:
            print(f"✗ Failed to remove {dir_path}: {e}")
    else:
        print(f"  Already removed: {dir_path}")
```

## Pattern 6: Main Script Structure

### Complete main script

```python
#!/usr/bin/env python3
"""
My Demo Skill - Main execution script

This script creates [describe what it creates].
"""

import sys
from pathlib import Path

# Define what this skill creates
CREATED_FILES = [
    "web/scratch/src/data/my-demo/data.json",
    "web/scratch/src/pages/MyDemo.tsx",
]

def generate_data():
    """Generate data files."""
    print("Generating data...")
    # ... your code here
    print("✓ Data generated")

def create_page():
    """Create page component."""
    print("Creating page...")
    # ... your code here
    print("✓ Page created")

def add_route():
    """Add route to application."""
    print("Adding route...")
    # ... your code here
    print("✓ Route added")

def verify():
    """Verify the page works."""
    print("Verifying...")
    # ... your code here
    print("✓ Verification complete")

def main():
    print("=" * 60)
    print("My Demo Skill")
    print("=" * 60)
    print()
    
    try:
        generate_data()
        create_page()
        add_route()
        verify()
        
        print()
        print("=" * 60)
        print("SUCCESS!")
        print("=" * 60)
        print()
        print("Created files:")
        for file_path in CREATED_FILES:
            print(f"  - {file_path}")
        print()
        print("Done!")
        
    except Exception as e:
        print()
        print("=" * 60)
        print("ERROR!")
        print("=" * 60)
        print()
        print(f"Error: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()
```

## Pattern 7: Colored Output

### Use colored output

```python
import sys

# ANSI color codes
RED = "\033[91m"
GREEN = "\033[92m"
YELLOW = "\033[93m"
BLUE = "\033[94m"
RESET = "\033[0m"

def log(message, color=RESET):
    """Print a colored message."""
    print(f"{color}{message}{RESET}")

def success(message):
    """Print a success message."""
    log(f"✓ {message}", GREEN)

def error(message):
    """Print an error message."""
    log(f"✗ {message}", RED)

def info(message):
    """Print an info message."""
    log(f"  {message}", BLUE)

# Usage
success("Data generated")
error("File not found")
info("Processing...")
```

## Pattern 8: Error Handling

### Handle errors gracefully

```python
import sys

def main():
    try:
        # Your code here
        pass
    except FileNotFoundError as e:
        print(f"ERROR: File not found: {e}")
        sys.exit(1)
    except PermissionError as e:
        print(f"ERROR: Permission denied: {e}")
        sys.exit(1)
    except Exception as e:
        print(f"ERROR: {e}")
        sys.exit(1)
```

### Check prerequisites

```python
def check_prerequisites():
    """Check that all prerequisites are met."""
    
    print("Checking prerequisites...")
    
    # Check that required files exist
    required_files = [
        "web/scratch/src/App.tsx",
        "web/scratch/src/components/NotebookTemplate.tsx",
    ]
    
    for file_path in required_files:
        if not Path(file_path).exists():
            print(f"ERROR: Required file not found: {file_path}")
            return False
    
    print("✓ All prerequisites met")
    return True
```

## Pattern 9: Configuration

### Use configuration constants

```python
# Configuration
SKILL_NAME = "my-demo-skill"
DATA_DIR = "web/scratch/src/data/my-demo"
PAGE_NAME = "MyDemo"
ROUTE_PATH = "/my-demo"

# Files created by this skill
CREATED_FILES = [
    f"{DATA_DIR}/data.json",
    f"web/scratch/src/pages/{PAGE_NAME}.tsx",
]

# Templates
TEMPLATE_DIR = "Skills/my-demo-skill/assets/templates"
PAGE_TEMPLATE = f"{TEMPLATE_DIR}/MyDemoTemplate.tsx"
```

## Pattern 10: Progress Indicators

### Show progress

```python
import time

def show_progress(steps):
    """Show progress for a list of steps."""
    
    total = len(steps)
    
    for i, step in enumerate(steps, 1):
        print(f"[{i}/{total}] {step}...")
        time.sleep(0.5)  # Simulate work
        print(f"  ✓ Done")

# Usage
steps = [
    "Generating data",
    "Creating page",
    "Adding route",
    "Verifying",
]

show_progress(steps)
```

## Summary

These patterns provide a foundation for creating demo skills. Mix and match them as needed for your specific use case.