197 lines
4.9 KiB
TypeScript
197 lines
4.9 KiB
TypeScript
|
|
import type {
|
||
|
|
Rack,
|
||
|
|
Module,
|
||
|
|
Port,
|
||
|
|
Vlan,
|
||
|
|
ServiceMap,
|
||
|
|
ServiceMapSummary,
|
||
|
|
ServiceNode,
|
||
|
|
ServiceEdge,
|
||
|
|
ModuleType,
|
||
|
|
PortType,
|
||
|
|
VlanMode,
|
||
|
|
NodeType,
|
||
|
|
} from '../types';
|
||
|
|
|
||
|
|
// ---- Core fetch wrapper ----
|
||
|
|
|
||
|
|
async function request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
||
|
|
const res = await fetch(`/api${endpoint}`, {
|
||
|
|
...options,
|
||
|
|
headers: { 'Content-Type': 'application/json', ...options.headers },
|
||
|
|
credentials: 'include',
|
||
|
|
});
|
||
|
|
|
||
|
|
const body = await res.json().catch(() => ({ data: null, error: `HTTP ${res.status}` }));
|
||
|
|
|
||
|
|
if (!res.ok) {
|
||
|
|
throw new Error((body as { error?: string }).error ?? `HTTP ${res.status}`);
|
||
|
|
}
|
||
|
|
|
||
|
|
return (body as { data: T }).data;
|
||
|
|
}
|
||
|
|
|
||
|
|
function get<T>(path: string) {
|
||
|
|
return request<T>(path);
|
||
|
|
}
|
||
|
|
|
||
|
|
function post<T>(path: string, data?: unknown) {
|
||
|
|
return request<T>(path, { method: 'POST', body: JSON.stringify(data) });
|
||
|
|
}
|
||
|
|
|
||
|
|
function put<T>(path: string, data?: unknown) {
|
||
|
|
return request<T>(path, { method: 'PUT', body: JSON.stringify(data) });
|
||
|
|
}
|
||
|
|
|
||
|
|
function del<T>(path: string) {
|
||
|
|
return request<T>(path, { method: 'DELETE' });
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---- Auth ----
|
||
|
|
|
||
|
|
const auth = {
|
||
|
|
me: () => get<{ authenticated: boolean }>('/auth/me'),
|
||
|
|
login: (username: string, password: string) =>
|
||
|
|
post<{ success: boolean }>('/auth/login', { username, password }),
|
||
|
|
logout: () => post<{ success: boolean }>('/auth/logout'),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Racks ----
|
||
|
|
|
||
|
|
const racks = {
|
||
|
|
list: () => get<Rack[]>('/racks'),
|
||
|
|
get: (id: string) => get<Rack>(`/racks/${id}`),
|
||
|
|
create: (data: { name: string; totalU?: number; location?: string; displayOrder?: number }) =>
|
||
|
|
post<Rack>('/racks', data),
|
||
|
|
update: (
|
||
|
|
id: string,
|
||
|
|
data: Partial<{ name: string; totalU: number; location: string; displayOrder: number }>
|
||
|
|
) => put<Rack>(`/racks/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/racks/${id}`),
|
||
|
|
addModule: (
|
||
|
|
rackId: string,
|
||
|
|
data: {
|
||
|
|
name: string;
|
||
|
|
type: ModuleType;
|
||
|
|
uPosition: number;
|
||
|
|
uSize?: number;
|
||
|
|
manufacturer?: string;
|
||
|
|
model?: string;
|
||
|
|
ipAddress?: string;
|
||
|
|
notes?: string;
|
||
|
|
portCount?: number;
|
||
|
|
portType?: PortType;
|
||
|
|
}
|
||
|
|
) => post<Module>(`/racks/${rackId}/modules`, data),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Modules ----
|
||
|
|
|
||
|
|
const modules = {
|
||
|
|
update: (
|
||
|
|
id: string,
|
||
|
|
data: Partial<{
|
||
|
|
name: string;
|
||
|
|
uPosition: number;
|
||
|
|
uSize: number;
|
||
|
|
manufacturer: string;
|
||
|
|
model: string;
|
||
|
|
ipAddress: string;
|
||
|
|
notes: string;
|
||
|
|
}>
|
||
|
|
) => put<Module>(`/modules/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/modules/${id}`),
|
||
|
|
getPorts: (id: string) => get<Port[]>(`/modules/${id}/ports`),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Ports ----
|
||
|
|
|
||
|
|
const ports = {
|
||
|
|
update: (
|
||
|
|
id: string,
|
||
|
|
data: {
|
||
|
|
label?: string;
|
||
|
|
mode?: VlanMode;
|
||
|
|
nativeVlan?: number | null;
|
||
|
|
notes?: string;
|
||
|
|
vlans?: Array<{ vlanId: string; tagged: boolean }>;
|
||
|
|
}
|
||
|
|
) => put<Port>(`/ports/${id}`, data),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- VLANs ----
|
||
|
|
|
||
|
|
const vlans = {
|
||
|
|
list: () => get<Vlan[]>('/vlans'),
|
||
|
|
create: (data: { vlanId: number; name: string; description?: string; color?: string }) =>
|
||
|
|
post<Vlan>('/vlans', data),
|
||
|
|
update: (id: string, data: Partial<{ name: string; description: string; color: string }>) =>
|
||
|
|
put<Vlan>(`/vlans/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/vlans/${id}`),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Service Maps ----
|
||
|
|
|
||
|
|
const maps = {
|
||
|
|
list: () => get<ServiceMapSummary[]>('/maps'),
|
||
|
|
get: (id: string) => get<ServiceMap>(`/maps/${id}`),
|
||
|
|
create: (data: { name: string; description?: string }) => post<ServiceMap>('/maps', data),
|
||
|
|
update: (id: string, data: Partial<{ name: string; description: string }>) =>
|
||
|
|
put<ServiceMap>(`/maps/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/maps/${id}`),
|
||
|
|
addNode: (
|
||
|
|
mapId: string,
|
||
|
|
data: {
|
||
|
|
label: string;
|
||
|
|
nodeType: NodeType;
|
||
|
|
positionX: number;
|
||
|
|
positionY: number;
|
||
|
|
metadata?: string;
|
||
|
|
color?: string;
|
||
|
|
icon?: string;
|
||
|
|
moduleId?: string;
|
||
|
|
}
|
||
|
|
) => post<ServiceNode>(`/maps/${mapId}/nodes`, data),
|
||
|
|
populate: (mapId: string) => post<ServiceMap>(`/maps/${mapId}/populate`),
|
||
|
|
addEdge: (
|
||
|
|
mapId: string,
|
||
|
|
data: {
|
||
|
|
sourceId: string;
|
||
|
|
targetId: string;
|
||
|
|
label?: string;
|
||
|
|
edgeType?: string;
|
||
|
|
animated?: boolean;
|
||
|
|
}
|
||
|
|
) => post<ServiceEdge>(`/maps/${mapId}/edges`, data),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Nodes ----
|
||
|
|
|
||
|
|
const nodes = {
|
||
|
|
update: (
|
||
|
|
id: string,
|
||
|
|
data: Partial<{
|
||
|
|
label: string;
|
||
|
|
positionX: number;
|
||
|
|
positionY: number;
|
||
|
|
metadata: string;
|
||
|
|
color: string;
|
||
|
|
icon: string;
|
||
|
|
moduleId: string | null;
|
||
|
|
}>
|
||
|
|
) => put<ServiceNode>(`/nodes/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/nodes/${id}`),
|
||
|
|
};
|
||
|
|
|
||
|
|
// ---- Edges ----
|
||
|
|
|
||
|
|
const edges = {
|
||
|
|
update: (
|
||
|
|
id: string,
|
||
|
|
data: Partial<{ label: string; edgeType: string; animated: boolean; metadata: string }>
|
||
|
|
) => put<ServiceEdge>(`/edges/${id}`, data),
|
||
|
|
delete: (id: string) => del<null>(`/edges/${id}`),
|
||
|
|
};
|
||
|
|
|
||
|
|
export const apiClient = { auth, racks, modules, ports, vlans, maps, nodes, edges };
|