2026-03-21 21:48:56 -05:00
|
|
|
generator client {
|
2026-03-21 22:32:25 -05:00
|
|
|
provider = "prisma-client-js"
|
|
|
|
|
// linux-musl-openssl-3.0.x = Alpine Linux (Docker); native = local dev/build
|
|
|
|
|
binaryTargets = ["native", "linux-musl-openssl-3.0.x"]
|
2026-03-21 21:48:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
datasource db {
|
|
|
|
|
provider = "sqlite"
|
|
|
|
|
url = env("DATABASE_URL")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NOTE: SQLite does not support Prisma enums.
|
|
|
|
|
// All enum-like fields are stored as String with validation enforced in the service layer.
|
|
|
|
|
// Valid values are documented in server/lib/constants.ts and client/src/types/index.ts
|
|
|
|
|
|
|
|
|
|
model Rack {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
totalU Int @default(42)
|
|
|
|
|
location String?
|
|
|
|
|
displayOrder Int @default(0)
|
|
|
|
|
modules Module[]
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Module {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
rackId String
|
|
|
|
|
rack Rack @relation(fields: [rackId], references: [id], onDelete: Cascade)
|
|
|
|
|
name String
|
|
|
|
|
type String // ModuleType: SWITCH | AGGREGATE_SWITCH | MODEM | ROUTER | NAS | PDU | PATCH_PANEL | SERVER | FIREWALL | AP | BLANK | OTHER
|
|
|
|
|
uPosition Int
|
|
|
|
|
uSize Int @default(1)
|
|
|
|
|
manufacturer String?
|
|
|
|
|
model String?
|
|
|
|
|
ipAddress String?
|
|
|
|
|
notes String?
|
|
|
|
|
ports Port[]
|
|
|
|
|
serviceNodes ServiceNode[]
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Port {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
moduleId String
|
|
|
|
|
module Module @relation(fields: [moduleId], references: [id], onDelete: Cascade)
|
|
|
|
|
portNumber Int
|
|
|
|
|
label String?
|
|
|
|
|
portType String @default("ETHERNET") // PortType: ETHERNET | SFP | SFP_PLUS | QSFP | CONSOLE | UPLINK
|
|
|
|
|
mode String @default("ACCESS") // VlanMode: ACCESS | TRUNK | HYBRID
|
|
|
|
|
nativeVlan Int?
|
|
|
|
|
vlans PortVlan[]
|
|
|
|
|
notes String?
|
2026-03-22 14:55:33 -05:00
|
|
|
|
|
|
|
|
// Connections — port can be source or target of a patch cable
|
|
|
|
|
sourceConnections Connection[] @relation("SourcePort")
|
|
|
|
|
targetConnections Connection[] @relation("TargetPort")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Connection {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
fromPortId String
|
|
|
|
|
fromPort Port @relation("SourcePort", fields: [fromPortId], references: [id], onDelete: Cascade)
|
|
|
|
|
toPortId String
|
|
|
|
|
toPort Port @relation("TargetPort", fields: [toPortId], references: [id], onDelete: Cascade)
|
|
|
|
|
color String? // Optional custom cable color
|
|
|
|
|
label String? // Optional cable label (e.g. "Cable #104")
|
2026-03-22 21:35:10 -05:00
|
|
|
edgeType String @default("bezier") // bezier | straight | step
|
2026-03-22 14:55:33 -05:00
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
|
|
|
|
|
@@unique([fromPortId, toPortId])
|
2026-03-21 21:48:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model Vlan {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
vlanId Int @unique
|
|
|
|
|
name String
|
|
|
|
|
description String?
|
|
|
|
|
color String?
|
|
|
|
|
ports PortVlan[]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model PortVlan {
|
|
|
|
|
portId String
|
|
|
|
|
port Port @relation(fields: [portId], references: [id], onDelete: Cascade)
|
|
|
|
|
vlanId String
|
|
|
|
|
vlan Vlan @relation(fields: [vlanId], references: [id], onDelete: Cascade)
|
|
|
|
|
tagged Boolean @default(false)
|
|
|
|
|
|
|
|
|
|
@@id([portId, vlanId])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- Service Mapper ---
|
|
|
|
|
|
|
|
|
|
model ServiceMap {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
name String
|
|
|
|
|
description String?
|
|
|
|
|
nodes ServiceNode[]
|
|
|
|
|
edges ServiceEdge[]
|
|
|
|
|
createdAt DateTime @default(now())
|
|
|
|
|
updatedAt DateTime @updatedAt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model ServiceNode {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
mapId String
|
|
|
|
|
map ServiceMap @relation(fields: [mapId], references: [id], onDelete: Cascade)
|
|
|
|
|
label String
|
|
|
|
|
nodeType String // NodeType: SERVICE | DATABASE | API | DEVICE | EXTERNAL | USER | VLAN | FIREWALL | LOAD_BALANCER | NOTE
|
|
|
|
|
positionX Float
|
|
|
|
|
positionY Float
|
|
|
|
|
metadata String?
|
|
|
|
|
color String?
|
|
|
|
|
icon String?
|
|
|
|
|
moduleId String?
|
|
|
|
|
module Module? @relation(fields: [moduleId], references: [id], onDelete: SetNull)
|
|
|
|
|
sourceEdges ServiceEdge[] @relation("EdgeSource")
|
|
|
|
|
targetEdges ServiceEdge[] @relation("EdgeTarget")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
model ServiceEdge {
|
|
|
|
|
id String @id @default(cuid())
|
|
|
|
|
mapId String
|
|
|
|
|
map ServiceMap @relation(fields: [mapId], references: [id], onDelete: Cascade)
|
|
|
|
|
sourceId String
|
|
|
|
|
source ServiceNode @relation("EdgeSource", fields: [sourceId], references: [id], onDelete: Cascade)
|
|
|
|
|
targetId String
|
|
|
|
|
target ServiceNode @relation("EdgeTarget", fields: [targetId], references: [id], onDelete: Cascade)
|
|
|
|
|
label String?
|
|
|
|
|
edgeType String @default("smoothstep")
|
|
|
|
|
animated Boolean @default(false)
|
|
|
|
|
metadata String?
|
|
|
|
|
}
|