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
This commit is contained in:
Mondo Diaz
2025-12-11 18:25:21 -06:00
parent 1793fd3a8f
commit 2d14d0f2f9
6 changed files with 306 additions and 6 deletions

View File

@@ -45,7 +45,8 @@ export async function getProject(name: string): Promise<Project> {
// Package API
export async function listPackages(projectName: string): Promise<Package[]> {
const response = await fetch(`${API_BASE}/project/${projectName}/packages`);
return handleResponse<Package[]>(response);
const data = await handleResponse<PaginatedResponse<Package>>(response);
return data.items;
}
export async function createPackage(projectName: string, data: { name: string; description?: string }): Promise<Package> {

View File

@@ -8,13 +8,28 @@ export interface Project {
created_by: string;
}
export interface TagSummary {
name: string;
artifact_id: string;
created_at: string;
}
export interface Package {
id: string;
project_id: string;
name: string;
description: string | null;
format: string;
platform: string;
created_at: string;
updated_at: string;
// Aggregated fields (from PackageDetailResponse)
tag_count?: number;
artifact_count?: number;
total_size?: number;
latest_tag?: string | null;
latest_upload_at?: string | null;
recent_tags?: TagSummary[];
}
export interface Artifact {