Import source: src/api/services/panel-service

Import the existing local project snapshot. This commit organizes existing files; it does not represent newly developed functionality.
This commit is contained in:
arsam
2026-09-18 23:10:04 +03:30
parent ff949c7889
commit 2dad56c97f
+244
View File
@@ -0,0 +1,244 @@
import { addMinutes } from "date-fns";
import type { ApiResponse, JobProgress, QueryParams } from "@/api/contracts/common";
import type {
DatabaseAdminTool,
DnsRecord,
SystemDiscovery,
Website,
} from "@/api/contracts/models";
import { mockResponse } from "@/api/client";
import { hasConfiguredHttpApi, httpPanelService } from "@/api/services/http-panel-service";
import {
accounts,
auditEntries,
automations,
backups,
currentUser,
databases,
dnsRecords,
domains,
files,
mailboxes,
metrics,
notifications,
resourceUsage,
runtimes,
securityFindings,
servers,
services,
websites,
} from "@/api/mocks/seed";
function searchBy<T>(items: T[], params: QueryParams | undefined, keys: Array<keyof T>) {
if (!params?.search) return items;
const term = params.search.toLowerCase();
return items.filter((item) =>
keys.some((key) =>
String(item[key] ?? "")
.toLowerCase()
.includes(term),
),
);
}
export const mockPanelService = {
auth: {
me: () => mockResponse(currentUser),
login: (email: string, password?: string, code?: string) => {
void password;
void code;
return mockResponse({
user: currentUser,
challenge: email.includes("2fa") ? "totp" : null,
sessionExpiresAt: addMinutes(new Date(), 45).toISOString(),
});
},
logout: () => mockResponse({ ok: true }),
},
dashboard: {
summary: () =>
mockResponse({
user: currentUser,
account: accounts[0],
server: servers[0],
accounts,
servers,
resources: resourceUsage,
services,
notifications,
metrics,
}),
},
websites: {
list: (params?: QueryParams) =>
mockResponse(searchBy(websites, params, ["name", "domain", "runtime"])),
create: (payload: Partial<Website>) =>
mockResponse({
id: `site-${Date.now()}`,
name: payload.name ?? "New website",
domain: payload.domain ?? "new.example.com",
runtime: payload.runtime ?? "PHP",
status: "healthy",
ssl: "healthy",
environment: "production",
cpuLimit: "1 vCPU",
memoryLimit: "1 GB",
lastDeployment: new Date().toISOString(),
} satisfies Website),
},
domains: {
list: (params?: QueryParams) => mockResponse(searchBy(domains, params, ["name", "type"])),
records: () => mockResponse(dnsRecords),
saveRecord: (record: Partial<DnsRecord>) =>
mockResponse({
id: record.id ?? `dns-${Date.now()}`,
name: record.name ?? "new.example.com.",
ttl: record.ttl ?? 14400,
class: "IN",
type: record.type ?? "A",
record: record.record ?? "198.51.100.40",
priority: record.priority,
} satisfies DnsRecord),
},
files: {
list: (params?: QueryParams) =>
mockResponse(searchBy(files, params, ["name", "path", "mime"])),
operation: (operation: string): Promise<ApiResponse<JobProgress>> =>
mockResponse({
id: `job-${Date.now()}`,
label: operation,
status: "running",
progress: 64,
startedAt: new Date().toISOString(),
message: "Mock operation is staged and will not touch the host filesystem.",
}),
},
databases: {
list: (params?: QueryParams) =>
mockResponse(searchBy(databases, params, ["name", "engine"])),
create: (name: string) => mockResponse({ id: `db-${Date.now()}`, name, status: "created" }),
adminTools: () =>
mockResponse<DatabaseAdminTool[]>([
{
id: "phpmyadmin",
name: "phpMyAdmin",
engine: "MySQL/MariaDB",
status: "available",
launchUrl: "/phpmyadmin/",
sso: false,
note: "Launches the local phpMyAdmin deployment in a separate browser tab.",
},
{
id: "adminer",
name: "Adminer",
engine: "MySQL, MariaDB, PostgreSQL",
status: "planned",
launchUrl: null,
sso: false,
note: "Ready in the API contract, not exposed on this host.",
},
{
id: "pgadmin",
name: "pgAdmin",
engine: "PostgreSQL",
status: "planned",
launchUrl: null,
sso: false,
note: "Ready in the API contract, not exposed on this host.",
},
]),
},
email: {
list: (params?: QueryParams) =>
mockResponse(searchBy(mailboxes, params, ["address", "domain"])),
create: (address: string) =>
mockResponse({ id: `mail-${Date.now()}`, address, status: "created" }),
},
metrics: {
history: () => mockResponse(metrics),
},
security: {
findings: () => mockResponse(securityFindings),
},
backups: {
list: () => mockResponse(backups),
create: (scope: string) =>
mockResponse<JobProgress>({
id: `job-${Date.now()}`,
label: `Create ${scope} backup`,
status: "queued",
progress: 0,
startedAt: new Date().toISOString(),
}),
},
automation: {
list: () => mockResponse(automations),
},
notifications: {
list: () => mockResponse(notifications),
},
audit: {
list: () => mockResponse(auditEntries),
},
software: {
runtimes: () => mockResponse(runtimes),
},
servers: {
list: () => mockResponse(servers),
services: () => mockResponse(services),
},
system: {
discovery: () =>
mockResponse<SystemDiscovery>({
detectedAt: new Date().toISOString(),
nginx: {
available: true,
sites: [
{
id: "mock-panel-site",
serverNames: ["cp.asabbagh.com"],
listens: ["443 ssl", "80"],
root: null,
proxyPasses: ["http://127.0.0.1:3110", "http://127.0.0.1:3020"],
tls: true,
source: "mock",
},
],
proxiedSites: [
{
id: "mock-panel-site",
serverNames: ["cp.asabbagh.com"],
listens: ["443 ssl", "80"],
root: null,
proxyPasses: ["http://127.0.0.1:3110", "http://127.0.0.1:3020"],
tls: true,
source: "mock",
},
],
},
docker: {
available: true,
containers: [
{
id: "mock-phpmyadmin",
name: "coaxyspanel-phpmyadmin",
image: "phpmyadmin:latest",
status: "Up",
ports: "127.0.0.1:8089->80/tcp",
},
],
},
currentPanel: {
hostname: "cp.asabbagh.com",
frontend: "http://127.0.0.1:3110",
backend: "http://127.0.0.1:3020",
},
}),
},
};
export type PanelService = typeof mockPanelService;
export const panelService: PanelService = hasConfiguredHttpApi
? (httpPanelService as PanelService)
: mockPanelService;