Skip to main content

Homepage Repos Backend Plugin

The Homepage Repos Backend provides repository persistence for the homepage Git Repositories section, allowing users to save and organize their frequently used repositories.

Overview

PropertyValue
Package@internal/plugin-homepage-repos-backend
TypeBackend
Plugin IDhomepage-repos
DatabasePostgreSQL via Knex

Architecture

API Endpoints

MethodEndpointDescription
GET/reposGet user's repos
GET/repos/by-group/:groupRefGet repos for group
POST/reposAdd new repository
DELETE/repos/:idDelete entire repo
DELETE/repos/:id/groups/:groupRefRemove repo from group
GET/autocompleteSearch existing repos
GET/user-groupsGet user's groups

Database Schema

homepage_repos

ColumnTypeDescription
idUUIDPrimary key
urlVARCHARGitHub repository URL
nameVARCHARRepository name
ownerVARCHARRepository owner
descriptionTEXTOptional description
group_refsJSONBArray of group refs
created_byVARCHARCreator user reference
created_atTIMESTAMPCreation time
updated_atTIMESTAMPLast update time

Request/Response Schemas

Create Repository

// POST /repos
interface CreateRepoRequest {
url: string; // GitHub URL
description?: string; // Optional description
groupRefs: string[]; // Groups to share with
}

// Zod schema
const createRepoSchema = z.object({
url: z.string().regex(/^https:\/\/github\.com\/[\w-]+\/[\w.-]+$/),
description: z.string().max(500).optional(),
groupRefs: z.array(z.string()).min(1),
});

Repository Response

interface Repository {
id: string;
url: string;
name: string;
owner: string;
description?: string;
groupRefs: string[];
createdBy: string;
createdAt: string;
updatedAt: string;
}

RepoStore Service

interface RepoStore {
// Repository operations
getRepos(groupRefs: string[]): Promise<Repository[]>;
getReposByGroup(groupRef: string): Promise<Repository[]>;
createRepo(input: CreateRepoInput, createdBy: string): Promise<Repository>;
deleteRepo(id: string): Promise<void>;
removeRepoFromGroup(id: string, groupRef: string): Promise<void>;
autocomplete(query: string): Promise<Repository[]>;
}

URL Validation

Repository URLs are validated and parsed:

class RepoUrlValidator {
validate(url: string): ParsedRepo {
const match = url.match(/^https:\/\/github\.com\/([\w-]+)\/([\w.-]+)$/);
if (!match) {
throw new InputError("Invalid GitHub repository URL");
}
return {
url,
owner: match[1],
name: match[2],
};
}
}

Accepted URL formats:

  • https://github.com/owner/repo
  • https://github.com/owner/repo.git (normalized)

Group-Based Access

Repositories are shared by group:

Usage Examples

Add Repository

curl -X POST http://localhost:7007/api/homepage-repos/repos \
-H "Content-Type: application/json" \
-d '{
"url": "https://github.com/badal-io/devex-backstage",
"description": "DevEx Backstage Platform",
"groupRefs": ["group:default/platform-team"]
}'

Get User's Repositories

curl http://localhost:7007/api/homepage-repos/repos

Response:

[
{
"id": "xxx",
"url": "https://github.com/badal-io/devex-backstage",
"name": "devex-backstage",
"owner": "badal-io",
"description": "DevEx Backstage Platform",
"groupRefs": ["group:default/platform-team"],
"createdBy": "user:default/john.doe",
"createdAt": "2024-01-15T10:00:00Z",
"updatedAt": "2024-01-15T10:00:00Z"
}
]

Search Repositories

curl "http://localhost:7007/api/homepage-repos/autocomplete?q=backstage"

Remove from Group

curl -X DELETE "http://localhost:7007/api/homepage-repos/repos/xxx/groups/group:default/platform-team"

Frontend Integration

The frontend combines saved repos with auto-detected ones: