Files
vibn-frontend/lib/coolify.ts

206 lines
6.2 KiB
TypeScript

/**
* Coolify API client for Vibn project provisioning.
*
* Used server-side only. Credentials from env vars:
* COOLIFY_URL — e.g. http://34.19.250.135:8000
* COOLIFY_API_TOKEN — admin bearer token
*/
const COOLIFY_URL = process.env.COOLIFY_URL ?? 'http://34.19.250.135:8000';
const COOLIFY_API_TOKEN = process.env.COOLIFY_API_TOKEN ?? '';
export interface CoolifyProject {
uuid: string;
name: string;
description?: string;
}
export interface CoolifyDatabase {
uuid: string;
name: string;
type: string;
status: string;
internal_db_url?: string;
external_db_url?: string;
}
export interface CoolifyApplication {
uuid: string;
name: string;
status: string;
fqdn?: string;
git_repository?: string;
git_branch?: string;
}
async function coolifyFetch(path: string, options: RequestInit = {}) {
const url = `${COOLIFY_URL}/api/v1${path}`;
const res = await fetch(url, {
...options,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${COOLIFY_API_TOKEN}`,
...(options.headers ?? {}),
},
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Coolify API error ${res.status} on ${path}: ${text}`);
}
if (res.status === 204) return null;
return res.json();
}
// ──────────────────────────────────────────────────
// Projects
// ──────────────────────────────────────────────────
export async function listProjects(): Promise<CoolifyProject[]> {
return coolifyFetch('/projects');
}
export async function createProject(name: string, description?: string): Promise<CoolifyProject> {
return coolifyFetch('/projects', {
method: 'POST',
body: JSON.stringify({ name, description }),
});
}
export async function getProject(uuid: string): Promise<CoolifyProject> {
return coolifyFetch(`/projects/${uuid}`);
}
export async function deleteProject(uuid: string): Promise<void> {
await coolifyFetch(`/projects/${uuid}`, { method: 'DELETE' });
}
// ──────────────────────────────────────────────────
// Databases
// ──────────────────────────────────────────────────
type DBType = 'postgresql' | 'mysql' | 'mariadb' | 'redis' | 'mongodb' | 'keydb';
export async function createDatabase(opts: {
projectUuid: string;
name: string;
type: DBType;
serverUuid?: string;
environmentName?: string;
}): Promise<CoolifyDatabase> {
const { projectUuid, name, type, serverUuid = '0', environmentName = 'production' } = opts;
return coolifyFetch(`/databases`, {
method: 'POST',
body: JSON.stringify({
project_uuid: projectUuid,
name,
type,
server_uuid: serverUuid,
environment_name: environmentName,
}),
});
}
export async function getDatabase(uuid: string): Promise<CoolifyDatabase> {
return coolifyFetch(`/databases/${uuid}`);
}
export async function deleteDatabase(uuid: string): Promise<void> {
await coolifyFetch(`/databases/${uuid}`, { method: 'DELETE' });
}
// ──────────────────────────────────────────────────
// Applications
// ──────────────────────────────────────────────────
export async function createApplication(opts: {
projectUuid: string;
name: string;
gitRepo: string; // e.g. "https://git.vibnai.com/mark/taskmaster.git"
gitBranch?: string;
serverUuid?: string;
environmentName?: string;
buildPack?: string; // nixpacks, static, dockerfile
ports?: string; // e.g. "3000"
}): Promise<CoolifyApplication> {
const {
projectUuid, name, gitRepo,
gitBranch = 'main',
serverUuid = process.env.COOLIFY_SERVER_UUID ?? 'jws4g4cgssss4cw48s488woc',
environmentName = 'production',
buildPack = 'nixpacks',
ports = '3000',
} = opts;
return coolifyFetch(`/applications`, {
method: 'POST',
body: JSON.stringify({
project_uuid: projectUuid,
name,
git_repository: gitRepo,
git_branch: gitBranch,
server_uuid: serverUuid,
environment_name: environmentName,
build_pack: buildPack,
ports_exposes: ports,
}),
});
}
/**
* Create a Coolify service for one app inside a Turborepo monorepo.
* Build command uses `turbo run build --filter` to target just that app.
*/
export async function createMonorepoAppService(opts: {
projectUuid: string;
appName: string;
gitRepo: string;
gitBranch?: string;
domain: string;
serverUuid?: string;
environmentName?: string;
}): Promise<CoolifyApplication> {
const {
projectUuid, appName, gitRepo,
gitBranch = 'main',
domain,
serverUuid = process.env.COOLIFY_SERVER_UUID ?? 'jws4g4cgssss4cw48s488woc',
environmentName = 'production',
} = opts;
return coolifyFetch(`/applications`, {
method: 'POST',
body: JSON.stringify({
project_uuid: projectUuid,
name: appName,
git_repository: gitRepo,
git_branch: gitBranch,
server_uuid: serverUuid,
environment_name: environmentName,
build_pack: 'nixpacks',
build_command: `pnpm install && turbo run build --filter=${appName}`,
start_command: `turbo run start --filter=${appName}`,
ports_exposes: '3000',
fqdn: `https://${domain}`,
}),
});
}
export async function listApplications(): Promise<CoolifyApplication[]> {
return coolifyFetch('/applications');
}
export async function deployApplication(uuid: string): Promise<{ deployment_uuid: string }> {
return coolifyFetch(`/applications/${uuid}/deploy`, { method: 'POST' });
}
export async function getApplication(uuid: string): Promise<CoolifyApplication> {
return coolifyFetch(`/applications/${uuid}`);
}
export async function getDeploymentLogs(deploymentUuid: string): Promise<{ logs: string }> {
return coolifyFetch(`/deployments/${deploymentUuid}/logs`);
}