import { apiRequest } from '../../lib/api'; import type { AppRelease, AppWithComponents } from '../../types/application'; import type { GiteaRepo } from '../../types/application'; import type { RuntimeResourceResponse, RuntimeWorkloadLogResponse } from '../../types/runtime'; export type LauncherVersion = { id: string; version: string; minimumVersion?: string | null; artifact: string; downloadUrl: string; releaseNotes?: string | null; repository?: string | null; branch?: string | null; commitSha?: string | null; isActive: boolean; createdAt?: string; updatedAt?: string; }; export type LauncherBuildJob = { id: string; target: string; repository?: string | null; branch: string; commitSha?: string | null; version: string; uploadPath: string; downloadUrl: string; artifact: string; status: 'PENDING' | 'RUNNING' | 'SUCCEEDED' | 'FAILED' | 'CANCELED'; requestedBy?: string | null; requestedByName?: string | null; requestedByEmail?: string | null; requestedByAvatarUrl?: string | null; createdBy?: string | null; createdByName?: string | null; createdByEmail?: string | null; createdByAvatarUrl?: string | null; logs?: string | null; startedAt?: string | null; finishedAt?: string | null; createdAt: string; updatedAt?: string; }; export type LauncherBackendDeployment = { namespace: string; deployment: string; container: string; currentImage?: string | null; available: boolean; source?: LauncherSource['backend']; latestBuild?: LauncherBuildJob | null; }; export type LauncherBackendDeployResult = { deployed: boolean; namespace: string; deployment: string; container: string; image: string; logs: string; }; export type DeploymentResourceLimits = { replicas?: number; cpuRequest?: string; cpuLimit?: string; memoryRequest?: string; memoryLimit?: string; }; export type LauncherBuildEnvVariable = { key: string; value: string; isSecret: boolean; }; export type LauncherSource = { repository?: string | null; branch?: string | null; commitSha?: string | null; client?: { repository?: string | null; branch?: string | null; commitSha?: string | null; }; backend?: { repository?: string | null; branch?: string | null; commitSha?: string | null; image?: string | null; dockerfile?: string | null; }; }; export type GiteaCommit = { sha: string; commit?: { message?: string; author?: { name?: string; date?: string; }; committer?: { name?: string; date?: string; }; }; author?: { login?: string; username?: string; full_name?: string; name?: string; avatar_url?: string; avatarUrl?: string; } | null; committer?: { login?: string; username?: string; full_name?: string; name?: string; avatar_url?: string; avatarUrl?: string; } | null; created?: string; }; export type LauncherAppLink = { id: string; appId: string; releaseId?: string | null; displayOrder: number; isEnabled: boolean; displayName?: string | null; description?: string | null; subtitle?: string | null; detailUrl?: string | null; videoPath?: string | null; iconKey?: string | null; launchUrl?: string | null; devAppPath?: string | null; execPath?: string | null; artifact?: string | null; createdAt: string; updatedAt?: string; app: AppWithComponents; release?: AppRelease | null; }; export type LauncherUnlinkedApp = AppWithComponents & { releases?: AppRelease[]; }; export function listLauncherVersions() { return apiRequest('/launcher/versions'); } export function createLauncherVersion(input: { version: string; minimumVersion?: string; artifact: string; downloadUrl: string; releaseNotes?: string; repository?: string; branch?: string; commitSha?: string; }) { return apiRequest<{ version: LauncherVersion }>('/launcher/versions', { method: 'POST', body: JSON.stringify(input) }); } export function linkLauncherVersionSource( versionId: string, input: { repository: string; branch?: string; commitSha?: string } ) { return apiRequest<{ version: LauncherVersion }>(`/launcher/versions/${versionId}/source`, { method: 'PATCH', body: JSON.stringify(input) }); } export function getLauncherSource() { return apiRequest<{ source: LauncherSource }>('/launcher/source'); } export function updateLauncherSource(input: { target?: 'launcher-client' | 'launcher-backend'; repository: string; branch?: string; commitSha?: string; image?: string; dockerfile?: string; }) { return apiRequest<{ source: LauncherSource }>('/launcher/source', { method: 'PATCH', body: JSON.stringify(input) }); } export function listPlatformRepos(limit = 50) { return apiRequest<{ owner: string | null; repos: GiteaRepo[] }>(`/gitea/repos?owner=platform&limit=${limit}`) .then((result) => result.repos); } export function listStudioRepos(limit = 50) { return apiRequest<{ owner: string | null; repos: GiteaRepo[] }>(`/gitea/repos?owner=studio&limit=${limit}`) .then((result) => result.repos); } export function listGiteaCommits( owner: string, repo: string, branch = 'develop', options?: { page?: number; limit?: number; since?: string } ) { const params = new URLSearchParams({ sha: branch, page: String(options?.page ?? 1), limit: String(options?.limit ?? 5) }); if (options?.since) params.set('since', options.since); return apiRequest<{ commits: GiteaCommit[] }>( `/gitea/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits?${params.toString()}` ).then((result) => result.commits); } export function listGiteaCommitsPage( owner: string, repo: string, branch = 'develop', options: { page: number; limit: number; since?: string } ) { const params = new URLSearchParams({ sha: branch, page: String(options.page), limit: String(options.limit) }); if (options.since) params.set('since', options.since); return apiRequest<{ commits: GiteaCommit[]; total: number | null; page: number; limit: number }>( `/gitea/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits?${params.toString()}` ); } export function getGiteaCommitDiff(owner: string, repo: string, sha: string) { return apiRequest<{ diff: string }>( `/gitea/repos/${encodeURIComponent(owner)}/${encodeURIComponent(repo)}/commits/${encodeURIComponent(sha)}/diff` ).then((result) => result.diff); } export function listLauncherBuildJobs(options?: { target?: string; page?: number; limit?: number; since?: string; }) { const params = new URLSearchParams(); if (options?.target) params.set('target', options.target); if (options?.page) params.set('page', String(options.page)); if (options?.limit) params.set('limit', String(options.limit)); if (options?.since) params.set('since', options.since); const query = params.toString() ? `?${params.toString()}` : ''; if (query) { return apiRequest<{ jobs: LauncherBuildJob[]; total: number; page: number; limit: number }>(`/launcher/builds${query}`) .then((result) => result.jobs); } return apiRequest('/launcher/builds'); } export function listLauncherBuildJobsPage(options: { target: string; page: number; limit: number; since?: string; }) { const params = new URLSearchParams({ target: options.target, page: String(options.page), limit: String(options.limit) }); if (options.since) params.set('since', options.since); return apiRequest<{ jobs: LauncherBuildJob[]; total: number; page: number; limit: number }>(`/launcher/builds?${params.toString()}`); } export function getLauncherBackendDeployment() { return apiRequest('/launcher/backend-deployment'); } export function deployLauncherBackend(image: string, resources?: DeploymentResourceLimits) { return apiRequest('/launcher/backend-deployment', { method: 'POST', body: JSON.stringify({ image, resources: resources && Object.keys(resources).length ? resources : undefined }) }); } export function listLauncherBuildEnv() { return apiRequest<{ variables: LauncherBuildEnvVariable[] }>('/launcher/build-env'); } export function saveLauncherBuildEnv(variables: LauncherBuildEnvVariable[]) { return apiRequest<{ variables: LauncherBuildEnvVariable[] }>('/launcher/build-env', { method: 'PUT', body: JSON.stringify({ variables }) }); } export function createLauncherBuildJob(input: { target?: string; repository?: string; branch?: string; commitSha?: string; version?: string; artifact?: string; uploadPath?: string; downloadUrl?: string; }) { return apiRequest<{ job: LauncherBuildJob }>('/launcher/builds', { method: 'POST', body: JSON.stringify(input) }); } export function listLauncherAppLinks() { return apiRequest<{ linked: LauncherAppLink[]; unlinked: LauncherUnlinkedApp[] }>('/launcher/app-links'); } export function syncLauncherAppsToAdminApps() { return apiRequest<{ syncedApps: number; syncedReleases: number }>('/launcher/app-links/sync-admin-apps', { method: 'POST' }); } export function createLauncherAppLink(input: { appId: string; releaseId?: string; displayOrder?: number; displayName?: string; description?: string; subtitle?: string; detailUrl?: string; videoPath?: string; iconKey?: string; launchUrl?: string; devAppPath?: string; execPath?: string; artifact?: string; }) { return apiRequest<{ link: LauncherAppLink }>('/launcher/app-links', { method: 'POST', body: JSON.stringify(input) }); } export function updateLauncherAppLink( id: string, input: Partial<{ displayOrder: number; isEnabled: boolean; displayName: string; description: string; subtitle: string; detailUrl: string; videoPath: string; iconKey: string; launchUrl: string; devAppPath: string; execPath: string; }> ) { return apiRequest<{ link: LauncherAppLink }>(`/launcher/app-links/${id}`, { method: 'PATCH', body: JSON.stringify(input) }); } export function moveLauncherAppLink(id: string, direction: 'up' | 'down') { return apiRequest<{ linked: LauncherAppLink[]; unlinked: LauncherUnlinkedApp[] }>(`/launcher/app-links/${id}/move`, { method: 'PATCH', body: JSON.stringify({ direction }) }); } export function deleteLauncherAppLink(id: string) { return apiRequest<{ deleted: boolean }>(`/launcher/app-links/${id}`, { method: 'DELETE' }); } export type RuntimeWorkloadEnvVariable = { key: string; value: string; isSecret: boolean; editable: boolean; source: string; }; export function loadLauncherRuntimeResources(namespace = 'studio-system') { return apiRequest(`/apps/runtime-namespaces/${encodeURIComponent(namespace)}/resources`); } export function loadRuntimeWorkloadEnv(namespace: string, kind: string, name: string) { return apiRequest<{ namespace: string; target: string; container: string | null; variables: RuntimeWorkloadEnvVariable[]; }>(`/runtime/workloads/${encodeURIComponent(namespace)}/${encodeURIComponent(kind.toLowerCase())}/${encodeURIComponent(name)}/env`); } export function saveRuntimeWorkloadEnv( namespace: string, kind: string, name: string, variables: Array<{ key: string; value: string; isSecret: boolean }> ) { return apiRequest<{ namespace: string; target: string; container: string | null; variables: RuntimeWorkloadEnvVariable[]; }>(`/runtime/workloads/${encodeURIComponent(namespace)}/${encodeURIComponent(kind.toLowerCase())}/${encodeURIComponent(name)}/env`, { method: 'PATCH', body: JSON.stringify({ variables }) }); } export function loadLauncherComponentLogs(namespace: string, kind: string, name: string, tail = 120) { return apiRequest( `/runtime/workloads/${encodeURIComponent(namespace)}/${encodeURIComponent(kind.toLowerCase())}/${encodeURIComponent(name)}/logs?tail=${tail}` ); } export function restartLauncherComponent(namespace: string, kind: string, name: string) { return apiRequest<{ ok: boolean; action: string; target: string; namespace: string }>( `/runtime/workloads/${encodeURIComponent(namespace)}/${encodeURIComponent(kind.toLowerCase())}/${encodeURIComponent(name)}/restart`, { method: 'POST' } ); }