441 lines
12 KiB
TypeScript
441 lines
12 KiB
TypeScript
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<LauncherVersion[]>('/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<LauncherBuildJob[]>('/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<LauncherBackendDeployment>('/launcher/backend-deployment');
|
|
}
|
|
|
|
export function deployLauncherBackend(image: string, resources?: DeploymentResourceLimits) {
|
|
return apiRequest<LauncherBackendDeployResult>('/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<RuntimeResourceResponse>(`/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<RuntimeWorkloadLogResponse>(
|
|
`/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' }
|
|
);
|
|
}
|