initial commit
Some checks failed
CI / Go — node-agent tests (push) Has been cancelled
CI / Go — edge-gateway build (push) Has been cancelled
CI / Node — lint, typecheck, test, build (push) Has been cancelled

This commit is contained in:
smueller
2026-06-26 10:45:08 +02:00
commit e37ea87b35
118 changed files with 7726 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
{
"name": "@hexahost/database",
"version": "0.0.0",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"scripts": {
"build": "tsc",
"typecheck": "tsc --noEmit",
"db:generate": "prisma generate",
"db:migrate": "prisma migrate dev",
"db:push": "prisma db push"
},
"dependencies": {
"@prisma/client": "^6.3.1"
},
"devDependencies": {
"@hexahost/typescript-config": "workspace:*",
"prisma": "^6.3.1",
"typescript": "^5.7.3"
}
}

View File

@@ -0,0 +1,263 @@
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
enum UserStatus {
ACTIVE
SUSPENDED
DELETED
}
enum GameServerStatus {
PENDING
PROVISIONING
STOPPED
STARTING
RUNNING
STOPPING
ERROR
DELETED
}
enum GameNodeStatus {
ONLINE
OFFLINE
MAINTENANCE
DRAINING
}
enum JobStatus {
PENDING
RUNNING
COMPLETED
FAILED
CANCELLED
}
model User {
id String @id @default(uuid())
email String @unique
username String @unique
status UserStatus @default(ACTIVE)
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
credentials UserCredential[]
sessions UserSession[]
platformRoles UserPlatformRole[]
gameServers GameServer[]
auditEvents AuditEvent[]
@@map("users")
}
model UserCredential {
id String @id @default(uuid())
userId String
passwordHash String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@map("user_credentials")
}
model UserSession {
id String @id @default(uuid())
userId String
tokenHash String @unique
expiresAt DateTime @db.Timestamptz(3)
revokedAt DateTime? @db.Timestamptz(3)
ipAddress String?
userAgent String?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
@@index([expiresAt])
@@map("user_sessions")
}
model PlatformRole {
id String @id @default(uuid())
name String @unique
description String?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
userRoles UserPlatformRole[]
@@map("platform_roles")
}
model UserPlatformRole {
id String @id @default(uuid())
userId String
roleId String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
role PlatformRole @relation(fields: [roleId], references: [id], onDelete: Cascade)
@@unique([userId, roleId])
@@index([userId])
@@index([roleId])
@@map("user_platform_roles")
}
model GameServer {
id String @id @default(uuid())
userId String
planId String?
nodeId String?
name String
status GameServerStatus @default(PENDING)
version Int @default(1)
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
user User @relation(fields: [userId], references: [id])
plan Plan? @relation(fields: [planId], references: [id])
node GameNode? @relation(fields: [nodeId], references: [id])
stateTransitions GameServerStateTransition[]
@@index([userId])
@@index([nodeId])
@@index([status])
@@map("game_servers")
}
model GameServerStateTransition {
id String @id @default(uuid())
gameServerId String
fromStatus GameServerStatus?
toStatus GameServerStatus
reason String?
metadata Json?
createdAt DateTime @default(now()) @db.Timestamptz(3)
gameServer GameServer @relation(fields: [gameServerId], references: [id], onDelete: Cascade)
@@index([gameServerId])
@@index([createdAt])
@@map("game_server_state_transitions")
}
model GameNode {
id String @id @default(uuid())
name String @unique
hostname String
status GameNodeStatus @default(OFFLINE)
maxServers Int @default(0)
activeServers Int @default(0)
metadata Json?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
gameServers GameServer[]
heartbeats GameNodeHeartbeat[]
@@map("game_nodes")
}
model GameNodeHeartbeat {
id String @id @default(uuid())
nodeId String
payload Json?
createdAt DateTime @default(now()) @db.Timestamptz(3)
node GameNode @relation(fields: [nodeId], references: [id], onDelete: Cascade)
@@index([nodeId])
@@index([createdAt])
@@map("game_node_heartbeats")
}
model Plan {
id String @id @default(uuid())
name String @unique
slug String @unique
description String?
isFree Boolean @default(false)
isActive Boolean @default(true)
maxRamMb Int
maxCpuCores Float
maxStorageMb Int
metadata Json?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
gameServers GameServer[]
@@map("plans")
}
model FeatureFlag {
id String @id @default(uuid())
key String @unique
description String?
enabled Boolean @default(false)
metadata Json?
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
@@map("feature_flags")
}
model SystemSetting {
id String @id @default(uuid())
key String @unique
value Json
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
@@map("system_settings")
}
model AuditEvent {
id String @id @default(uuid())
userId String?
action String
entityType String?
entityId String?
metadata Json?
ipAddress String?
createdAt DateTime @default(now()) @db.Timestamptz(3)
user User? @relation(fields: [userId], references: [id], onDelete: SetNull)
@@index([userId])
@@index([action])
@@index([entityType, entityId])
@@index([createdAt])
@@map("audit_events")
}
model JobRecord {
id String @id @default(uuid())
queue String
jobName String
status JobStatus @default(PENDING)
payload Json?
result Json?
error String?
attempts Int @default(0)
startedAt DateTime? @db.Timestamptz(3)
completedAt DateTime? @db.Timestamptz(3)
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime @updatedAt @db.Timestamptz(3)
@@index([queue, status])
@@index([createdAt])
@@map("job_records")
}

View File

@@ -0,0 +1,40 @@
export { PrismaClient, Prisma } from '@prisma/client';
export type {
User,
UserCredential,
UserSession,
PlatformRole,
UserPlatformRole,
GameServer,
GameServerStateTransition,
GameNode,
GameNodeHeartbeat,
Plan,
FeatureFlag,
SystemSetting,
AuditEvent,
JobRecord,
} from '@prisma/client';
import { PrismaClient } from '@prisma/client';
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined;
};
export const prisma =
globalForPrisma.prisma ??
new PrismaClient({
log:
process.env['LOG_LEVEL'] === 'debug'
? ['query', 'info', 'warn', 'error']
: ['warn', 'error'],
});
if (process.env['NODE_ENV'] !== 'production') {
globalForPrisma.prisma = prisma;
}
export function createPrismaClient(): PrismaClient {
return new PrismaClient();
}

View File

@@ -0,0 +1,9 @@
{
"extends": "@hexahost/typescript-config/library.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}