add support for listing available repos

This commit is contained in:
CaptOrb 2025-08-28 12:43:40 +01:00
parent 3a7e93611b
commit 6b7e6a5c01
4 changed files with 186 additions and 207 deletions

View File

@ -123,7 +123,7 @@ paths:
- in: path
name: id
schema:
type: string
type: number
required: true
description: Repository ID
requestBody:
@ -202,8 +202,7 @@ components:
type: object
properties:
id:
type: string
example: "123"
type: number
name:
type: string
example: "molci"

View File

@ -2,6 +2,7 @@ import * as arctic from "arctic";
import { config } from "../../config/env";
import type { Forge } from "../../types/forge";
import type { ForgeUser } from "../../types/forgeuser";
import type { GiteaRepo } from "../../types/gitearepo";
import type { Repository } from "../../types/openapi";
export class GiteaForge implements Forge {
@ -58,10 +59,27 @@ export class GiteaForge implements Forge {
const res = await fetch(`${config.GITEA_URL}/api/v1/user/repos`, {
headers: { Authorization: `token ${accessToken}` },
});
if (!res.ok) throw new Error(`Failed to fetch repos: ${res.status}`);
return res.json();
}
if (!res.ok) {
if (res.status === 401) throw new Error("Unauthorised");
throw new Error(`Failed to fetch repos: ${res.status}`);
}
const repos: GiteaRepo[] = await res.json();
return repos.map((repo) => ({
id: repo.id,
name: repo.name,
full_name: repo.full_name,
private: repo.private,
url: repo.html_url,
description: repo.description,
owner: {
id: repo.owner.id,
login: repo.owner.login,
avatar_url: repo.owner.avatar_url,
},
}));
}
async validateToken(accessToken: string) {
try {
await this.getUserInfo(accessToken);

View File

@ -0,0 +1,13 @@
export interface GiteaRepo {
id: number;
name: string;
full_name: string;
private: boolean;
html_url: string;
owner: {
id: number;
login: string;
avatar_url: string;
};
description?: string;
}

View File

@ -1,213 +1,162 @@
import type { Context, UnknownParams } from "openapi-backend";
import type {
Context,
UnknownParams,
} from 'openapi-backend';
declare namespace Components {
namespace Schemas {
export interface Error {
/**
* Error message
* example:
* Repository not found
*/
error: string;
/**
* Error code for programmatic handling
* example:
* REPO_NOT_FOUND
*/
code: string;
/**
* Additional error details
*/
details?: {
[name: string]: any;
};
}
export interface Repository {
/**
* example:
* 123
*/
id?: string;
/**
* example:
* molci
*/
name?: string;
/**
* example:
* gitea
*/
forge?: "gitea";
}
export interface RepositoryConfig {
repo?: Repository;
configured_at?: string; // date-time
webhook_id?: string;
}
export interface RepositoryConfigInput {
settings: {
[name: string]: any;
};
}
}
namespace Schemas {
export interface Error {
/**
* Error message
* example:
* Repository not found
*/
error: string;
/**
* Error code for programmatic handling
* example:
* REPO_NOT_FOUND
*/
code: string;
/**
* Additional error details
*/
details?: {
[name: string]: any;
};
}
export interface Repository {
id?: number;
/**
* example:
* molci
*/
name?: string;
/**
* example:
* gitea
*/
forge?: "gitea";
}
export interface RepositoryConfig {
repo?: Repository;
configured_at?: string; // date-time
webhook_id?: string;
}
export interface RepositoryConfigInput {
settings: {
[name: string]: any;
};
}
}
}
declare namespace Paths {
namespace ConfigureRepo {
namespace Parameters {
export type Id = string;
}
export interface PathParameters {
id: Parameters.Id;
}
export type RequestBody = Components.Schemas.RepositoryConfigInput;
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig;
export type $400 = Components.Schemas.Error;
export type $401 = Components.Schemas.Error;
export type $404 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace GetRepo {
namespace Parameters {
export type Id = string;
}
export interface PathParameters {
id: Parameters.Id;
}
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig;
export type $400 = Components.Schemas.Error;
export type $401 = Components.Schemas.Error;
export type $404 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace ListAvailableRepos {
namespace Responses {
export type $200 = Components.Schemas.Repository[];
export type $401 = Components.Schemas.Error;
export type $403 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace ListConfiguredRepos {
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig[];
export type $401 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace ConfigureRepo {
namespace Parameters {
export type Id = number;
}
export interface PathParameters {
id: Parameters.Id;
}
export type RequestBody = Components.Schemas.RepositoryConfigInput;
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig;
export type $400 = Components.Schemas.Error;
export type $401 = Components.Schemas.Error;
export type $404 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace GetRepo {
namespace Parameters {
export type Id = string;
}
export interface PathParameters {
id: Parameters.Id;
}
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig;
export type $400 = Components.Schemas.Error;
export type $401 = Components.Schemas.Error;
export type $404 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace ListAvailableRepos {
namespace Responses {
export type $200 = Components.Schemas.Repository[];
export type $401 = Components.Schemas.Error;
export type $403 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
namespace ListConfiguredRepos {
namespace Responses {
export type $200 = Components.Schemas.RepositoryConfig[];
export type $401 = Components.Schemas.Error;
export type $500 = Components.Schemas.Error;
}
}
}
export interface Operations {
/**
* GET /repos/available
*/
["listAvailableRepos"]: {
requestBody: any;
params: UnknownParams;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<
any,
UnknownParams,
UnknownParams,
UnknownParams,
UnknownParams
>;
response:
| Paths.ListAvailableRepos.Responses.$200
| Paths.ListAvailableRepos.Responses.$401
| Paths.ListAvailableRepos.Responses.$403
| Paths.ListAvailableRepos.Responses.$500;
};
/**
* GET /repos/configured
*/
["listConfiguredRepos"]: {
requestBody: any;
params: UnknownParams;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<
any,
UnknownParams,
UnknownParams,
UnknownParams,
UnknownParams
>;
response:
| Paths.ListConfiguredRepos.Responses.$200
| Paths.ListConfiguredRepos.Responses.$401
| Paths.ListConfiguredRepos.Responses.$500;
};
/**
* GET /repo/{id}
*/
["getRepo"]: {
requestBody: any;
params: Paths.GetRepo.PathParameters;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<
any,
Paths.GetRepo.PathParameters,
UnknownParams,
UnknownParams,
UnknownParams
>;
response:
| Paths.GetRepo.Responses.$200
| Paths.GetRepo.Responses.$400
| Paths.GetRepo.Responses.$401
| Paths.GetRepo.Responses.$404
| Paths.GetRepo.Responses.$500;
};
/**
* PUT /repo/{id}
*/
["configureRepo"]: {
requestBody: Paths.ConfigureRepo.RequestBody;
params: Paths.ConfigureRepo.PathParameters;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<
Paths.ConfigureRepo.RequestBody,
Paths.ConfigureRepo.PathParameters,
UnknownParams,
UnknownParams,
UnknownParams
>;
response:
| Paths.ConfigureRepo.Responses.$200
| Paths.ConfigureRepo.Responses.$400
| Paths.ConfigureRepo.Responses.$401
| Paths.ConfigureRepo.Responses.$404
| Paths.ConfigureRepo.Responses.$500;
};
/**
* GET /repos/available
*/
['listAvailableRepos']: {
requestBody: any;
params: UnknownParams;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<any, UnknownParams, UnknownParams, UnknownParams, UnknownParams>;
response: Paths.ListAvailableRepos.Responses.$200 | Paths.ListAvailableRepos.Responses.$401 | Paths.ListAvailableRepos.Responses.$403 | Paths.ListAvailableRepos.Responses.$500;
}
/**
* GET /repos/configured
*/
['listConfiguredRepos']: {
requestBody: any;
params: UnknownParams;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<any, UnknownParams, UnknownParams, UnknownParams, UnknownParams>;
response: Paths.ListConfiguredRepos.Responses.$200 | Paths.ListConfiguredRepos.Responses.$401 | Paths.ListConfiguredRepos.Responses.$500;
}
/**
* GET /repo/{id}
*/
['getRepo']: {
requestBody: any;
params: Paths.GetRepo.PathParameters;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<any, Paths.GetRepo.PathParameters, UnknownParams, UnknownParams, UnknownParams>;
response: Paths.GetRepo.Responses.$200 | Paths.GetRepo.Responses.$400 | Paths.GetRepo.Responses.$401 | Paths.GetRepo.Responses.$404 | Paths.GetRepo.Responses.$500;
}
/**
* PUT /repo/{id}
*/
['configureRepo']: {
requestBody: Paths.ConfigureRepo.RequestBody;
params: Paths.ConfigureRepo.PathParameters;
query: UnknownParams;
headers: UnknownParams;
cookies: UnknownParams;
context: Context<Paths.ConfigureRepo.RequestBody, Paths.ConfigureRepo.PathParameters, UnknownParams, UnknownParams, UnknownParams>;
response: Paths.ConfigureRepo.Responses.$200 | Paths.ConfigureRepo.Responses.$400 | Paths.ConfigureRepo.Responses.$401 | Paths.ConfigureRepo.Responses.$404 | Paths.ConfigureRepo.Responses.$500;
}
}
export type OperationContext<operationId extends keyof Operations> =
Operations[operationId]["context"];
export type OperationResponse<operationId extends keyof Operations> =
Operations[operationId]["response"];
export type HandlerResponse<
ResponseBody,
ResponseModel = Record<string, any>,
> = ResponseModel & { _t?: ResponseBody };
export type OperationHandlerResponse<operationId extends keyof Operations> =
HandlerResponse<OperationResponse<operationId>>;
export type OperationHandler<
operationId extends keyof Operations,
HandlerArgs extends unknown[] = unknown[],
> = (
...params: [OperationContext<operationId>, ...HandlerArgs]
) => Promise<OperationHandlerResponse<operationId>>;
export type OperationContext<operationId extends keyof Operations> = Operations[operationId]["context"];
export type OperationResponse<operationId extends keyof Operations> = Operations[operationId]["response"];
export type HandlerResponse<ResponseBody, ResponseModel = Record<string, any>> = ResponseModel & { _t?: ResponseBody };
export type OperationHandlerResponse<operationId extends keyof Operations> = HandlerResponse<OperationResponse<operationId>>;
export type OperationHandler<operationId extends keyof Operations, HandlerArgs extends unknown[] = unknown[]> = (...params: [OperationContext<operationId>, ...HandlerArgs]) => Promise<OperationHandlerResponse<operationId>>;
export type Error = Components.Schemas.Error;
export type Repository = Components.Schemas.Repository;