db: Drizzle schemas on domain Postgres schemas, baseline migration, reorg SQL
- pgSchema tables for auth, money, house, ref, games, cs, animaldex, site, meta (lists excluded via schemaFilter; runtime list tables are managed by meta.*) - drizzle/ baseline matches the reorged DB exactly (catalog diff = 0 on rehearsal) - db/reorg: one-time SQL that moves the flat public schema (rehearsed on a prod copy) - scripts/db-migrate.ts: migrator with --init to record the baseline and a guard against running the baseline on a non-empty, unrecorded database
This commit is contained in:
@@ -2,20 +2,21 @@ import {
|
||||
boolean,
|
||||
check,
|
||||
date,
|
||||
numeric,
|
||||
index,
|
||||
integer,
|
||||
jsonb,
|
||||
pgTable,
|
||||
text,
|
||||
unique
|
||||
} from 'drizzle-orm/pg-core';
|
||||
import { gamesSchema, refSchema } from './schemas';
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { user } from './auth';
|
||||
import { games, pokemon } from './catch-em-all';
|
||||
import { trackerGames, trackerItems } from './game-tracker';
|
||||
import { id, timestamps } from './helpers';
|
||||
|
||||
export const pokemonResearch = pgTable('pokemon_research', {
|
||||
export const pokemonResearch = refSchema.table('pokemon_research', {
|
||||
pokemonId: integer('pokemon_id')
|
||||
.primaryKey()
|
||||
.references(() => pokemon.id, { onDelete: 'cascade' }),
|
||||
@@ -36,7 +37,7 @@ export const pokemonResearch = pgTable('pokemon_research', {
|
||||
.notNull()
|
||||
});
|
||||
|
||||
export const pokemonDexNumbers = pgTable(
|
||||
export const pokemonDexNumbers = refSchema.table(
|
||||
'pokemon_dex_numbers',
|
||||
{
|
||||
id: id(),
|
||||
@@ -53,7 +54,7 @@ export const pokemonDexNumbers = pgTable(
|
||||
(t) => [unique().on(t.pokemonId, t.gameId, t.dex), index().on(t.gameId)]
|
||||
);
|
||||
|
||||
export const pokemonMoves = pgTable('pokemon_moves', {
|
||||
export const pokemonMoves = refSchema.table('pokemon_moves', {
|
||||
id: integer('id').primaryKey(),
|
||||
name: text('name').notNull(),
|
||||
type: text('type').notNull(),
|
||||
@@ -65,7 +66,7 @@ export const pokemonMoves = pgTable('pokemon_moves', {
|
||||
target: text('target').notNull()
|
||||
});
|
||||
|
||||
export const pokemonLearnsets = pgTable(
|
||||
export const pokemonLearnsets = refSchema.table(
|
||||
'pokemon_learnsets',
|
||||
{
|
||||
id: id(),
|
||||
@@ -78,7 +79,7 @@ export const pokemonLearnsets = pgTable(
|
||||
(t) => [unique().on(t.pokemonId, t.versionGroup)]
|
||||
);
|
||||
|
||||
export const pokemonGameResearch = pgTable('pokemon_game_research', {
|
||||
export const pokemonGameResearch = refSchema.table('pokemon_game_research', {
|
||||
gameId: integer('game_id')
|
||||
.primaryKey()
|
||||
.references(() => games.id, { onDelete: 'cascade' }),
|
||||
@@ -86,7 +87,7 @@ export const pokemonGameResearch = pgTable('pokemon_game_research', {
|
||||
regions: text('regions').array().notNull()
|
||||
});
|
||||
|
||||
export const pokemonJourneys = pgTable(
|
||||
export const pokemonJourneys = gamesSchema.table(
|
||||
'pokemon_journeys',
|
||||
{
|
||||
id: id(),
|
||||
@@ -103,10 +104,13 @@ export const pokemonJourneys = pgTable(
|
||||
completed: boolean('completed').notNull().default(false),
|
||||
...timestamps
|
||||
},
|
||||
(t) => [unique().on(t.userId, t.gameId)]
|
||||
(t) => [
|
||||
unique().on(t.userId, t.gameId),
|
||||
check('pokemon_journeys_stage_check', sql`${t.stage} IN ('story','postgame','collection')`)
|
||||
]
|
||||
);
|
||||
|
||||
export const pokemonSeen = pgTable(
|
||||
export const pokemonSeen = gamesSchema.table(
|
||||
'pokemon_seen',
|
||||
{
|
||||
id: id(),
|
||||
@@ -124,7 +128,7 @@ export const pokemonSeen = pgTable(
|
||||
(t) => [unique().on(t.userId, t.gameId, t.pokemonId), index().on(t.userId)]
|
||||
);
|
||||
|
||||
export const pokemonCatches = pgTable(
|
||||
export const pokemonCatches = gamesSchema.table(
|
||||
'pokemon_catches',
|
||||
{
|
||||
id: id(),
|
||||
@@ -157,13 +161,14 @@ export const pokemonCatches = pgTable(
|
||||
(t) => [
|
||||
index().on(t.userId, t.gameId, t.pokemonId),
|
||||
unique().on(t.userId, t.gameId, t.partySlot),
|
||||
check('pokemon_catch_level', sql`${t.level} between 1 and 100`),
|
||||
check('pokemon_party_slot', sql`${t.partySlot} between 1 and 6`),
|
||||
check('pokemon_four_moves', sql`cardinality(${t.moves}) <= 4`)
|
||||
check('pokemon_catches_level_check', sql`${t.level} between 1 and 100`),
|
||||
check('pokemon_catches_party_slot_check', sql`${t.partySlot} between 1 and 6`),
|
||||
check('pokemon_catches_moves_check', sql`cardinality(${t.moves}) <= 4`),
|
||||
check('pokemon_catches_stage_check', sql`${t.stage} IN ('story','postgame','collection')`)
|
||||
]
|
||||
);
|
||||
|
||||
export const pokemonMilestones = pgTable(
|
||||
export const pokemonMilestones = gamesSchema.table(
|
||||
'pokemon_milestones',
|
||||
{
|
||||
id: id(),
|
||||
@@ -184,7 +189,7 @@ export const pokemonMilestones = pgTable(
|
||||
(t) => [unique().on(t.userId, t.gameId, t.key)]
|
||||
);
|
||||
|
||||
export const trackerRanks = pgTable(
|
||||
export const trackerRanks = gamesSchema.table(
|
||||
'tracker_ranks',
|
||||
{
|
||||
id: id(),
|
||||
@@ -200,14 +205,12 @@ export const trackerRanks = pgTable(
|
||||
},
|
||||
(t) => [
|
||||
unique().on(t.userId, t.gameId),
|
||||
check(
|
||||
'tracker_rank_range',
|
||||
sql`${t.level} between 1 and 10000 and ${t.prestige} between 0 and 1000`
|
||||
)
|
||||
check('tracker_ranks_level_check', sql`${t.level} between 1 and 10000`),
|
||||
check('tracker_ranks_prestige_check', sql`${t.prestige} between 0 and 1000`)
|
||||
]
|
||||
);
|
||||
|
||||
export const trackerWeaponRanks = pgTable(
|
||||
export const trackerWeaponRanks = gamesSchema.table(
|
||||
'tracker_weapon_ranks',
|
||||
{
|
||||
id: id(),
|
||||
@@ -223,14 +226,12 @@ export const trackerWeaponRanks = pgTable(
|
||||
},
|
||||
(t) => [
|
||||
unique().on(t.userId, t.itemId),
|
||||
check(
|
||||
'tracker_weapon_rank_range',
|
||||
sql`${t.level} between 1 and 10000 and ${t.prestige} between 0 and 1000`
|
||||
)
|
||||
check('tracker_weapon_ranks_level_check', sql`${t.level} between 1 and 10000`),
|
||||
check('tracker_weapon_ranks_prestige_check', sql`${t.prestige} between 0 and 1000`)
|
||||
]
|
||||
);
|
||||
|
||||
export const trackerChallenges = pgTable(
|
||||
export const trackerChallenges = refSchema.table(
|
||||
'tracker_challenges',
|
||||
{
|
||||
id: id(),
|
||||
@@ -249,7 +250,7 @@ export const trackerChallenges = pgTable(
|
||||
(t) => [unique().on(t.gameId, t.key)]
|
||||
);
|
||||
|
||||
export const trackerChallengeProgress = pgTable(
|
||||
export const trackerChallengeProgress = gamesSchema.table(
|
||||
'tracker_challenge_progress',
|
||||
{
|
||||
id: id(),
|
||||
@@ -263,10 +264,13 @@ export const trackerChallengeProgress = pgTable(
|
||||
done: boolean('done').notNull().default(false),
|
||||
...timestamps
|
||||
},
|
||||
(t) => [unique().on(t.userId, t.challengeId)]
|
||||
(t) => [
|
||||
unique().on(t.userId, t.challengeId),
|
||||
check('tracker_challenge_progress_current_check', sql`${t.current} >= 0`)
|
||||
]
|
||||
);
|
||||
|
||||
export const osuEntries = pgTable(
|
||||
export const osuEntries = gamesSchema.table(
|
||||
'osu_entries',
|
||||
{
|
||||
id: id(),
|
||||
@@ -282,18 +286,23 @@ export const osuEntries = pgTable(
|
||||
skill: text('skill').notNull().default('stamina'),
|
||||
bpm: integer('bpm'),
|
||||
duration: integer('duration'),
|
||||
accuracy: text('accuracy'),
|
||||
accuracy: numeric('accuracy', { mode: 'number' }),
|
||||
combo: integer('combo'),
|
||||
misses: integer('misses'),
|
||||
pp: text('pp'),
|
||||
pp: numeric('pp', { mode: 'number' }),
|
||||
mods: text('mods').notNull().default('NM'),
|
||||
rate: text('rate').notNull().default('1.00'),
|
||||
rate: numeric('rate', { precision: 4, scale: 2, mode: 'number' })
|
||||
.notNull()
|
||||
.default(sql`1.00`),
|
||||
achieved: boolean('achieved').notNull().default(false),
|
||||
playedOn: date('played_on').notNull(),
|
||||
notes: text('notes').notNull().default(''),
|
||||
...timestamps
|
||||
},
|
||||
(t) => [index().on(t.userId, t.kind)]
|
||||
(t) => [
|
||||
index().on(t.userId, t.kind),
|
||||
check('osu_entries_kind_check', sql`${t.kind} IN ('score','goal','training')`)
|
||||
]
|
||||
);
|
||||
|
||||
export type PokemonCatch = typeof pokemonCatches.$inferSelect;
|
||||
|
||||
Reference in New Issue
Block a user