Rebuild atomcms-next foundation on Prisma (align to habbo-next reference)

Replace the superseded Drizzle monorepo scaffold with a single-app Prisma 7
data layer, mirroring the proven habbo-next approach to the shared Arcturus
emulator DB (introspect/conform only, idempotent SQL migrations via a custom
runner; never migrate-diff).

- prisma/schema.prisma: User, UsersCurrency (composite PK), Ban, WebsiteSetting
  mapped to AtomCMS's default.sql columns; client generated to src/generated/prisma
- src/lib/prisma.ts: PrismaMariaDb adapter singleton; src/env.ts zod env
- src/lib/services: siteSettings (cached setting() equivalent) + CurrencyType enum
- prisma/migrations + scripts/apply-migrations.ts: idempotent CMS-table runner

Verified: prisma generate OK, tsc --noEmit exit 0, vitest 6/6 pass.
This commit is contained in:
Simo committed 2026-06-27 15:26:40 +02:00
1 parent 7bd4f2b28e
commit b5bc7f6daf
44 files changed
+1279 -511

No files matched your search

+102
View File
@@ -0,0 +1,102 @@
// AtomCMS → Next.js conversion data layer.
//
// The database schema is OWNED by the Arcturus Morningstar emulator and shared
// live with the game server. This app conforms to that schema — it never
// generates or migrates the emulator tables. CMS-only tables (website_*) are
// created via idempotent SQL in prisma/migrations/*.sql (see apply-migrations).
//
// This is the first slice (users / users_currency / bans / website_settings);
// the full table set will be regenerated via `prisma db pull` once a live DB
// connection is available.
generator client {
provider = "prisma-client"
output = "../src/generated/prisma"
}
datasource db {
provider = "mysql"
}
enum users_gender {
M
F
}
enum bans_type {
account
ip
machine
super
}
/// Emulator-owned core account table (users). Column names mirror default.sql.
model User {
id Int @id @default(autoincrement())
username String @unique(map: "username") @db.VarChar(25)
realName String @default("KREWS DEV") @map("real_name") @db.VarChar(25)
password String @db.VarChar(64)
mail String? @db.VarChar(500)
mailVerified String @default("0") @map("mail_verified")
accountCreated Int @map("account_created")
accountDayOfBirth Int @default(0) @map("account_day_of_birth")
lastLogin Int @default(0) @map("last_login")
lastOnline Int @default(0) @map("last_online")
motto String @default("") @db.VarChar(127)
look String @default("") @db.VarChar(256)
gender users_gender @default(M)
rank Int @default(1)
credits Int @default(2500)
pixels Int @default(500)
points Int @default(10)
online String @default("0")
// Ephemeral SSO ticket rotated on each emulator handshake ({HOTEL_NAME}-{uuid}).
// The emulator validates it byte-for-byte when the Nitro/Flash client connects.
authTicket String @default("") @map("auth_ticket") @db.VarChar(256)
ipRegister String @map("ip_register") @db.VarChar(45)
ipCurrent String @map("ip_current") @db.VarChar(45)
machineId String @default("") @map("machine_id") @db.VarChar(64)
homeRoom Int @default(0) @map("home_room")
secretKey String? @map("secret_key") @db.VarChar(40)
pincode String? @db.VarChar(11)
extraRank Int? @map("extra_rank")
@@map("users")
}
/// Emulator-owned multi-currency ledger. Composite PK (user_id, type), no id.
/// Currency types are fixed: Credits=-1, Duckets=0, Diamonds=5, Points=101.
model UsersCurrency {
userId Int @map("user_id")
type Int
amount Int @default(0)
@@id([userId, type])
@@map("users_currency")
}
/// Emulator-owned bans table. Active bans are those with ban_expire > now().
model Ban {
id Int @id @default(autoincrement())
userId Int @map("user_id")
ip String @default("") @db.VarChar(50)
machineId String @default("") @map("machine_id") @db.VarChar(255)
userStaffId Int @map("user_staff_id")
timestamp Int
banExpire Int @default(0) @map("ban_expire")
banReason String @default("") @map("ban_reason") @db.VarChar(200)
type bans_type @default(account)
cfhTopic Int @default(-1) @map("cfh_topic")
@@map("bans")
}
/// CMS-owned key/value settings (created by prisma/migrations, not the emulator).
model WebsiteSetting {
id BigInt @id @default(autoincrement()) @db.UnsignedBigInt
key String @unique(map: "website_settings_key_unique") @db.VarChar(255)
value String @db.Text
comment String? @db.VarChar(255)
@@map("website_settings")
}