157 lines
5.5 KiB
JavaScript
157 lines
5.5 KiB
JavaScript
|
|
/**
|
||
|
|
* Initial schema backfill migration.
|
||
|
|
*
|
||
|
|
* Reproduces the 7-table DDL that `scripts/setup-neon-db.js` has been the
|
||
|
|
* documented source-of-truth bootstrap for since the project's first commit.
|
||
|
|
* Every statement uses `CREATE TABLE IF NOT EXISTS` so the migration is
|
||
|
|
* idempotent against:
|
||
|
|
*
|
||
|
|
* 1. A brand-new Neon branch (creates all tables fresh).
|
||
|
|
* 2. An existing env where `npm run setup-db` has already run pre-convoy
|
||
|
|
* (every CREATE is a no-op; the `pgmigrations` row is the only change).
|
||
|
|
* 3. An existing env where the legacy `scripts/add-*.js` / `scripts/fix-*.js`
|
||
|
|
* jobs added columns beyond the bootstrap shape — those columns are
|
||
|
|
* preserved (CREATE TABLE IF NOT EXISTS does not touch existing tables).
|
||
|
|
*
|
||
|
|
* The shape is byte-equivalent to `scripts/setup-neon-db.js` HEAD as of
|
||
|
|
* `convoy/migration-tool` branch. If those scripts diverge again in the
|
||
|
|
* future, ship a new dated migration alongside the script edit — do NOT
|
||
|
|
* edit this file in place (this file is now itself an append-only artifact;
|
||
|
|
* mutating it would silently corrupt any env that has it recorded as run).
|
||
|
|
*
|
||
|
|
* Down-migration is intentionally a hard stub. See `down()` below.
|
||
|
|
*
|
||
|
|
* @type {import('node-pg-migrate').ColumnDefinitions | undefined}
|
||
|
|
*/
|
||
|
|
export const shorthands = undefined;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* @param {import('node-pg-migrate').MigrationBuilder} pgm
|
||
|
|
* @returns {void}
|
||
|
|
*/
|
||
|
|
export const up = (pgm) => {
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS users (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
email VARCHAR(255) UNIQUE NOT NULL,
|
||
|
|
password VARCHAR(255) NOT NULL,
|
||
|
|
role VARCHAR(50) DEFAULT 'user',
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS cards (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
name VARCHAR(255) NOT NULL,
|
||
|
|
set_name VARCHAR(255),
|
||
|
|
set_code VARCHAR(50),
|
||
|
|
card_number VARCHAR(50),
|
||
|
|
rarity VARCHAR(50),
|
||
|
|
game VARCHAR(50) NOT NULL,
|
||
|
|
mana_cost VARCHAR(50),
|
||
|
|
cmc INTEGER,
|
||
|
|
card_type VARCHAR(255),
|
||
|
|
colors JSONB,
|
||
|
|
oracle_text TEXT,
|
||
|
|
power VARCHAR(10),
|
||
|
|
toughness VARCHAR(10),
|
||
|
|
image_url TEXT,
|
||
|
|
stock_image_url TEXT,
|
||
|
|
current_price DECIMAL(10,2),
|
||
|
|
market_price DECIMAL(10,2),
|
||
|
|
scryfall_id VARCHAR(255) UNIQUE,
|
||
|
|
verified BOOLEAN DEFAULT false,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS user_cards (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE,
|
||
|
|
quantity INTEGER DEFAULT 1,
|
||
|
|
condition VARCHAR(50) DEFAULT 'NM',
|
||
|
|
is_foil BOOLEAN DEFAULT false,
|
||
|
|
notes TEXT,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE(user_id, card_id, is_foil)
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS collections (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
name VARCHAR(255) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
is_public BOOLEAN DEFAULT false,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS collection_cards (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
collection_id INTEGER REFERENCES collections(id) ON DELETE CASCADE,
|
||
|
|
card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE,
|
||
|
|
quantity INTEGER DEFAULT 1,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE(collection_id, card_id)
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS decks (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
name VARCHAR(255) NOT NULL,
|
||
|
|
description TEXT,
|
||
|
|
game VARCHAR(50),
|
||
|
|
is_public BOOLEAN DEFAULT false,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
|
||
|
|
pgm.sql(`
|
||
|
|
CREATE TABLE IF NOT EXISTS deck_cards (
|
||
|
|
id SERIAL PRIMARY KEY,
|
||
|
|
deck_id INTEGER REFERENCES decks(id) ON DELETE CASCADE,
|
||
|
|
card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE,
|
||
|
|
quantity INTEGER DEFAULT 1,
|
||
|
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
UNIQUE(deck_id, card_id)
|
||
|
|
)
|
||
|
|
`);
|
||
|
|
};
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Down-migration is a hard stub. Rolling back the initial schema would drop
|
||
|
|
* every user, card, collection, and deck row in the database — and the
|
||
|
|
* `pgmigrations` row itself — leaving nothing to migrate forward from. If
|
||
|
|
* you genuinely need a clean schema for testing, branch the Neon database
|
||
|
|
* (instant + cheap) and run `npm run migrate up` against the branch instead
|
||
|
|
* of rolling this migration back.
|
||
|
|
*
|
||
|
|
* If a future schema correction needs to mutate one of the seven bootstrap
|
||
|
|
* tables, write a NEW dated migration (`npm run migrate create <name>`)
|
||
|
|
* with a real `down` — do NOT remove this stub.
|
||
|
|
*
|
||
|
|
* @returns {void}
|
||
|
|
*/
|
||
|
|
export const down = () => {
|
||
|
|
throw new Error(
|
||
|
|
'[migration:1779853647564_initial-schema] Refusing to drop the initial schema. ' +
|
||
|
|
'Rolling back this migration would erase every users / cards / collections / decks row ' +
|
||
|
|
'in the database. If you need a clean schema for testing, branch the Neon database and ' +
|
||
|
|
'run `npm run migrate up` against the branch instead. See migrations/1779853647564_initial-schema.js ' +
|
||
|
|
"down()'s docstring for the long form."
|
||
|
|
);
|
||
|
|
};
|