Refactor code structure for improved readability and maintainability
This commit is contained in:
181
docs/01-conceptos/data-model.md
Normal file
181
docs/01-conceptos/data-model.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# Modelo de datos — Entidades y esquema sugerido
|
||||
|
||||
## Diagrama ER (texto)
|
||||
|
||||
Game ↔ RomFile (1‑N)
|
||||
Game ↔ Artwork (1‑N)
|
||||
Game ↔ Platform (N‑N)
|
||||
Game ↔ Tag (N‑N)
|
||||
Game ↔ Purchase (1‑N)
|
||||
Game ↔ PriceHistory (1‑N)
|
||||
|
||||
---
|
||||
|
||||
## Entidades principales (campos sugeridos)
|
||||
|
||||
### Game
|
||||
|
||||
- `id` (cuid) — identificador.
|
||||
- `title` (string) — nombre principal.
|
||||
- `slug` (string) — único, legible.
|
||||
- `description` (text) — opcional.
|
||||
- `releaseDate` (DateTime?) — fecha principal.
|
||||
- `igdbId`, `rawgId`, `thegamesdbId` (Int?) — ids externos.
|
||||
- `extra` (String?) — JSON serializado (compatible con SQLite); usar `JSON.parse`/`JSON.stringify` al leer/escribir.
|
||||
- `createdAt`, `updatedAt`.
|
||||
|
||||
### Platform
|
||||
|
||||
- `id`, `name`, `slug`, `generation`.
|
||||
|
||||
### RomFile
|
||||
|
||||
- `id`, `path`, `filename`, `checksum` (unique), `size` (int), `format`, `hashes` (String? — JSON serializado, ej.: {"crc32":"...","md5":"..."}), `status` (active/missing), `addedAt`, `lastSeenAt`, `gameId`.
|
||||
|
||||
### Artwork
|
||||
|
||||
- `id`, `gameId`, `type` (cover/screenshot), `sourceUrl`, `localPath`, `width`, `height`, `fetchedAt`.
|
||||
|
||||
### Purchase
|
||||
|
||||
- `id`, `gameId`, `priceCents` (int), `currency`, `store`, `date`, `receiptPath`.
|
||||
|
||||
### PriceHistory
|
||||
|
||||
- `id`, `gameId`, `priceCents`, `currency`, `recordedAt`, `source`.
|
||||
|
||||
### Tag
|
||||
|
||||
- `id`, `name` (unique), color.
|
||||
|
||||
### User (opcional)
|
||||
|
||||
- `id`, `name`, `email` (unique), `passwordHash`, `role`.
|
||||
|
||||
---
|
||||
|
||||
## Índices y constraints recomendados
|
||||
|
||||
- `RomFile.checksum` — **UNIQUE** (detectar duplicados).
|
||||
- `Game`: índice por `title` y `slug` (`slug` único).
|
||||
- Composite unique sugerido: `[primaryPlatformId, title, releaseDate]` para evitar duplicados de una misma versión/plataforma.
|
||||
- Índices para búsquedas frecuentes (title, platform, tags).
|
||||
|
||||
---
|
||||
|
||||
## Fragmento `schema.prisma` (ejemplo)
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "sqlite" // usar SQLite para desarrollo; cambiar a postgresql en producción si se necesita JSON nativo
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
generator client {
|
||||
provider = "prisma-client-js"
|
||||
}
|
||||
|
||||
model Game {
|
||||
id String @id @default(cuid())
|
||||
title String
|
||||
slug String @unique
|
||||
description String?
|
||||
releaseDate DateTime?
|
||||
igdbId Int? @unique
|
||||
rawgId Int? @unique
|
||||
thegamesdbId Int? @unique
|
||||
platforms Platform[]
|
||||
romFiles RomFile[]
|
||||
artworks Artwork[]
|
||||
tags Tag[]
|
||||
extra String? // JSON serializado (usar JSON.parse/JSON.stringify para leer y escribir)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
@@index([title])
|
||||
@@unique([slug])
|
||||
}
|
||||
|
||||
model Platform {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
slug String @unique
|
||||
games Game[]
|
||||
}
|
||||
|
||||
model RomFile {
|
||||
id String @id @default(cuid())
|
||||
path String
|
||||
filename String
|
||||
checksum String @unique
|
||||
size Int
|
||||
format String
|
||||
hashes String? // JSON serializado (ej.: {"crc32":"...","md5":"..."})
|
||||
game Game? @relation(fields: [gameId], references: [id])
|
||||
gameId String?
|
||||
addedAt DateTime @default(now())
|
||||
lastSeenAt DateTime?
|
||||
status String @default("active")
|
||||
@@index([checksum])
|
||||
}
|
||||
|
||||
model Artwork {
|
||||
id String @id @default(cuid())
|
||||
game Game @relation(fields: [gameId], references: [id])
|
||||
gameId String
|
||||
type String
|
||||
sourceUrl String
|
||||
localPath String?
|
||||
width Int?
|
||||
height Int?
|
||||
fetchedAt DateTime @default(now())
|
||||
}
|
||||
|
||||
model Purchase {
|
||||
id String @id @default(cuid())
|
||||
game Game @relation(fields: [gameId], references: [id])
|
||||
gameId String
|
||||
priceCents Int
|
||||
currency String
|
||||
store String?
|
||||
date DateTime
|
||||
receiptPath String?
|
||||
}
|
||||
|
||||
model PriceHistory {
|
||||
id String @id @default(cuid())
|
||||
game Game @relation(fields: [gameId], references: [id])
|
||||
gameId String
|
||||
priceCents Int
|
||||
currency String
|
||||
recordedAt DateTime @default(now())
|
||||
source String?
|
||||
}
|
||||
|
||||
model Tag {
|
||||
id String @id @default(cuid())
|
||||
name String @unique
|
||||
games Game[]
|
||||
}
|
||||
```
|
||||
|
||||
> Nota: para monedas se recomienda almacenar `priceCents` (int) para compatibilidad; si se usa Postgres se puede optar por `Decimal`. Nota: SQLite no soporta tipos JSON nativos; en este ejemplo se usan `String` para JSON serializado. Si migras a Postgres, puedes usar `Json`/`JsonB` para campos flexibles.
|
||||
|
||||
---
|
||||
|
||||
## Migraciones y evolución del esquema
|
||||
|
||||
- Usar **Prisma Migrate** para versionar cambios.
|
||||
- Preferir migraciones no destructivas (añadir columnas `NULL` y rellenarlas en background).
|
||||
- Mantener seeds de desarrollo para pruebas manuales y reproducibles.
|
||||
|
||||
---
|
||||
|
||||
## Fuentes
|
||||
|
||||
- Prisma schema conventions, patterns para modelado relacional y técnicas de deduplicación de archivos.
|
||||
|
||||
---
|
||||
|
||||
**Metadatos**
|
||||
Autor: Quasar (investigación automatizada)
|
||||
Última actualización: 2026-02-07
|
||||
Reference in New Issue
Block a user