Rename terminology to industry standard terms

- Grove → Project
- Tree → Package
- Fruit → Artifact
- Graft → Tag
- Cultivate → Upload
- Harvest → Download

Updated across:
- Backend models, schemas, and routes
- Frontend types, API client, and components
- README documentation
- API endpoints now use /project/:project/packages pattern

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-08 10:38:44 -06:00
parent ce1dd760c4
commit d382e5d6b7
12 changed files with 470 additions and 485 deletions

View File

@@ -1,4 +1,4 @@
import { Grove, Tree, Graft, Fruit, CultivateResponse } from './types';
import { Project, Package, Tag, Artifact, UploadResponse } from './types';
const API_BASE = '/api/v1';
@@ -10,78 +10,78 @@ async function handleResponse<T>(response: Response): Promise<T> {
return response.json();
}
// Grove API
export async function listGroves(): Promise<Grove[]> {
const response = await fetch(`${API_BASE}/groves`);
return handleResponse<Grove[]>(response);
// Project API
export async function listProjects(): Promise<Project[]> {
const response = await fetch(`${API_BASE}/projects`);
return handleResponse<Project[]>(response);
}
export async function createGrove(data: { name: string; description?: string; is_public?: boolean }): Promise<Grove> {
const response = await fetch(`${API_BASE}/groves`, {
export async function createProject(data: { name: string; description?: string; is_public?: boolean }): Promise<Project> {
const response = await fetch(`${API_BASE}/projects`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return handleResponse<Grove>(response);
return handleResponse<Project>(response);
}
export async function getGrove(name: string): Promise<Grove> {
const response = await fetch(`${API_BASE}/groves/${name}`);
return handleResponse<Grove>(response);
export async function getProject(name: string): Promise<Project> {
const response = await fetch(`${API_BASE}/projects/${name}`);
return handleResponse<Project>(response);
}
// Tree API
export async function listTrees(groveName: string): Promise<Tree[]> {
const response = await fetch(`${API_BASE}/grove/${groveName}/trees`);
return handleResponse<Tree[]>(response);
// Package API
export async function listPackages(projectName: string): Promise<Package[]> {
const response = await fetch(`${API_BASE}/project/${projectName}/packages`);
return handleResponse<Package[]>(response);
}
export async function createTree(groveName: string, data: { name: string; description?: string }): Promise<Tree> {
const response = await fetch(`${API_BASE}/grove/${groveName}/trees`, {
export async function createPackage(projectName: string, data: { name: string; description?: string }): Promise<Package> {
const response = await fetch(`${API_BASE}/project/${projectName}/packages`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return handleResponse<Tree>(response);
return handleResponse<Package>(response);
}
// Graft API
export async function listGrafts(groveName: string, treeName: string): Promise<Graft[]> {
const response = await fetch(`${API_BASE}/grove/${groveName}/${treeName}/grafts`);
return handleResponse<Graft[]>(response);
// Tag API
export async function listTags(projectName: string, packageName: string): Promise<Tag[]> {
const response = await fetch(`${API_BASE}/project/${projectName}/${packageName}/tags`);
return handleResponse<Tag[]>(response);
}
export async function createGraft(groveName: string, treeName: string, data: { name: string; fruit_id: string }): Promise<Graft> {
const response = await fetch(`${API_BASE}/grove/${groveName}/${treeName}/graft`, {
export async function createTag(projectName: string, packageName: string, data: { name: string; artifact_id: string }): Promise<Tag> {
const response = await fetch(`${API_BASE}/project/${projectName}/${packageName}/tags`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
return handleResponse<Graft>(response);
return handleResponse<Tag>(response);
}
// Fruit API
export async function getFruit(fruitId: string): Promise<Fruit> {
const response = await fetch(`${API_BASE}/fruit/${fruitId}`);
return handleResponse<Fruit>(response);
// Artifact API
export async function getArtifact(artifactId: string): Promise<Artifact> {
const response = await fetch(`${API_BASE}/artifact/${artifactId}`);
return handleResponse<Artifact>(response);
}
// Upload
export async function cultivate(groveName: string, treeName: string, file: File, tag?: string): Promise<CultivateResponse> {
export async function uploadArtifact(projectName: string, packageName: string, file: File, tag?: string): Promise<UploadResponse> {
const formData = new FormData();
formData.append('file', file);
if (tag) {
formData.append('tag', tag);
}
const response = await fetch(`${API_BASE}/grove/${groveName}/${treeName}/cultivate`, {
const response = await fetch(`${API_BASE}/project/${projectName}/${packageName}/upload`, {
method: 'POST',
body: formData,
});
return handleResponse<CultivateResponse>(response);
return handleResponse<UploadResponse>(response);
}
// Download URL
export function getDownloadUrl(groveName: string, treeName: string, ref: string): string {
return `${API_BASE}/grove/${groveName}/${treeName}/+/${ref}`;
export function getDownloadUrl(projectName: string, packageName: string, ref: string): string {
return `${API_BASE}/project/${projectName}/${packageName}/+/${ref}`;
}