diff --git a/src/api/services/http-panel-service.ts b/src/api/services/http-panel-service.ts new file mode 100644 index 0000000..dd09f80 --- /dev/null +++ b/src/api/services/http-panel-service.ts @@ -0,0 +1,125 @@ +import type { ApiResponse, JobProgress, QueryParams } from "@/api/contracts/common"; +import type { DnsRecord, Website } from "@/api/contracts/models"; + +const configuredApiBaseUrl = process.env.NEXT_PUBLIC_API_BASE_URL?.trim(); +export const hasConfiguredHttpApi = Boolean(configuredApiBaseUrl); +const apiBaseUrl = configuredApiBaseUrl?.replace(/\/$/, ""); + +type RequestOptions = { + method?: "GET" | "POST" | "PUT" | "DELETE"; + body?: unknown; + params?: QueryParams; +}; + +function queryString(params?: QueryParams) { + const search = new URLSearchParams(); + if (params?.search) search.set("search", params.search); + if (params?.pagination) { + search.set("page", String(params.pagination.page)); + search.set("pageSize", String(params.pagination.pageSize)); + } + const value = search.toString(); + return value ? `?${value}` : ""; +} + +async function request(path: string, options: RequestOptions = {}): Promise> { + if (!apiBaseUrl) { + throw new Error("NEXT_PUBLIC_API_BASE_URL is not configured."); + } + + const url = + apiBaseUrl === "." || apiBaseUrl === "same-origin" + ? path + : apiBaseUrl.endsWith("/api") && path.startsWith("/api/") + ? `${apiBaseUrl}${path.slice(4)}` + : `${apiBaseUrl}${path}`; + + const response = await fetch(`${url}${queryString(options.params)}`, { + method: options.method ?? "GET", + credentials: "include", + headers: + options.body === undefined + ? undefined + : { + "Content-Type": "application/json", + }, + body: options.body === undefined ? undefined : JSON.stringify(options.body), + cache: "no-store", + }); + + const json = (await response.json()) as ApiResponse; + return json; +} + +export const httpPanelService = { + auth: { + me: () => request("/api/auth/me"), + login: (email: string, password = "correct-password", code?: string) => + request("/api/auth/login", { + method: "POST", + body: { email, password, code }, + }), + logout: () => request("/api/auth/logout", { method: "POST" }), + }, + dashboard: { + summary: () => request("/api/dashboard/summary"), + }, + websites: { + list: (params?: QueryParams) => request("/api/websites", { params }), + create: (payload: Partial) => + request("/api/websites", { method: "POST", body: payload }), + }, + domains: { + list: (params?: QueryParams) => request("/api/domains", { params }), + records: () => request("/api/domains/dom-1/dns"), + saveRecord: (record: Partial) => + record.id + ? request(`/api/domains/dom-1/dns/${record.id}`, { method: "PUT", body: record }) + : request("/api/domains/dom-1/dns", { method: "POST", body: record }), + }, + files: { + list: (params?: QueryParams) => request("/api/files", { params }), + operation: (operation: string): Promise> => + request("/api/files/operations", { method: "POST", body: { operation } }), + }, + databases: { + list: (params?: QueryParams) => request("/api/databases", { params }), + create: (name: string) => request("/api/databases", { method: "POST", body: { name } }), + adminTools: () => request("/api/databases/admin-tools"), + }, + email: { + list: (params?: QueryParams) => request("/api/email/accounts", { params }), + create: (address: string) => + request("/api/email/accounts", { method: "POST", body: { address } }), + }, + metrics: { + history: () => request("/api/metrics/history"), + }, + security: { + findings: () => request("/api/security/findings"), + }, + backups: { + list: () => request("/api/backups"), + create: (scope: string) => + request("/api/backups", { method: "POST", body: { scope } }), + }, + automation: { + list: () => request("/api/automation"), + }, + notifications: { + list: () => request("/api/notifications"), + }, + audit: { + list: () => request("/api/audit-logs"), + }, + software: { + runtimes: () => request("/api/software/runtimes"), + }, + servers: { + list: () => request("/api/servers"), + services: () => request("/api/servers/services"), + }, + system: { + discovery: () => request("/api/system/discovery"), + }, +};