deckhearth/migrations/1787693311000_add-custom-games.js
Randall Stillwell c0051dd6d5 feat(designer): game targeting and custom game spaces
- game system selector: standalone, existing system (MTG/Pokemon/Lorcana/
  SWU/FaB/One Piece/Sorcery/Grand Archive — codes match catalog imports),
  or a user's custom game
- custom_games table + CRUD API (private per user, unique names)
- /games hub with create form; /games/[id] space with rename, delete,
  card gallery, and ?game= deep-link into the designer
- catalog twin resolves game: system code, custom game name, or 'Custom'
- my-designs shows each design's game association
- migration 1787693311000
2026-08-24 21:01:04 -05:00

45 lines
1.4 KiB
JavaScript

/**
* Phase 2 — game targeting + custom game spaces.
*
* custom_games: private, per-user named game systems. Cards, frames, and
* (later) symbols can belong to one.
*
* custom_cards.game_target: 'custom' (default, standalone designs) or the
* code of an existing system ('MTG', 'Pokemon', 'Lorcana', ...).
* custom_cards.custom_game_id: set when the design belongs to a user's
* custom game.
*/
export const up = (pgm) => {
pgm.sql(`
CREATE TABLE IF NOT EXISTS custom_games (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_custom_games_user_name UNIQUE (user_id, name)
)
`);
pgm.sql(`
ALTER TABLE custom_cards
ADD COLUMN IF NOT EXISTS game_target VARCHAR(50) NOT NULL DEFAULT 'custom',
ADD COLUMN IF NOT EXISTS custom_game_id INTEGER REFERENCES custom_games(id) ON DELETE SET NULL
`);
pgm.sql(`
CREATE INDEX IF NOT EXISTS idx_custom_cards_custom_game_id
ON custom_cards(custom_game_id)
`);
};
export const down = (pgm) => {
pgm.sql(`
ALTER TABLE custom_cards
DROP COLUMN IF EXISTS custom_game_id,
DROP COLUMN IF EXISTS game_target
`);
pgm.sql(`DROP TABLE IF EXISTS custom_games CASCADE`);
};