Files
orchard/backend/app/database.py
Mondo Diaz d24f635ed1 Enhance packages API with pagination, filtering, and metadata
Backend changes:
- Add format and platform columns to Package model with validation
- Add database migrations for new columns with indexes
- Create PackageDetailResponse schema with aggregated fields:
  - tag_count, artifact_count, total_size
  - latest_tag, latest_upload_at
  - recent_tags (last 5 tags)
- Update list_packages endpoint:
  - Add pagination (page, limit)
  - Add search by name/description
  - Add sort (name, created_at, updated_at) and order (asc, desc)
  - Add format and platform filters
  - Return aggregated metadata for each package
- Add GET /api/v1/project/{project}/packages/{package_name} endpoint
  - Returns single package with full metadata
  - Optional include_tags parameter for all tags
- Update create_package to accept format and platform

Frontend changes:
- Update Package type with format, platform, and optional metadata fields
- Update listPackages to handle paginated response

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 18:25:21 -06:00

83 lines
2.5 KiB
Python

from sqlalchemy import create_engine, text
from sqlalchemy.orm import sessionmaker, Session
from typing import Generator
import logging
from .config import get_settings
from .models import Base
settings = get_settings()
logger = logging.getLogger(__name__)
engine = create_engine(settings.database_url, pool_pre_ping=True)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
def init_db():
"""Create all tables and run migrations"""
Base.metadata.create_all(bind=engine)
# Run migrations for schema updates
_run_migrations()
def _run_migrations():
"""Run manual migrations for schema updates"""
migrations = [
# Add format_metadata column to artifacts table
"""
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'artifacts' AND column_name = 'format_metadata'
) THEN
ALTER TABLE artifacts ADD COLUMN format_metadata JSONB DEFAULT '{}';
END IF;
END $$;
""",
# Add format column to packages table
"""
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'packages' AND column_name = 'format'
) THEN
ALTER TABLE packages ADD COLUMN format VARCHAR(50) DEFAULT 'generic' NOT NULL;
CREATE INDEX IF NOT EXISTS idx_packages_format ON packages(format);
END IF;
END $$;
""",
# Add platform column to packages table
"""
DO $$
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'packages' AND column_name = 'platform'
) THEN
ALTER TABLE packages ADD COLUMN platform VARCHAR(50) DEFAULT 'any' NOT NULL;
CREATE INDEX IF NOT EXISTS idx_packages_platform ON packages(platform);
END IF;
END $$;
""",
]
with engine.connect() as conn:
for migration in migrations:
try:
conn.execute(text(migration))
conn.commit()
except Exception as e:
logger.warning(f"Migration failed (may already be applied): {e}")
def get_db() -> Generator[Session, None, None]:
"""Dependency for getting database sessions"""
db = SessionLocal()
try:
yield db
finally:
db.close()