import { integer, primaryKey, real, sqliteTable, text } from 'drizzle-orm/sqlite-core' // Drizzle schema for game state. Single-player by design: exactly ONE save row ever exists // (no auth/accounts), so every table hangs off saves.id but only one save is in play. // Column names/types here are the source of truth; matching CREATE TABLE statements live // in lib/db/client.ts (DDL) and must stay in sync with this file. export const saves = sqliteTable('saves', { id: integer('id').primaryKey({ autoIncrement: true }), // Seed for the deterministic world generator — same seed always regenerates the same world. seed: text('seed').notNull(), turn: integer('turn').notNull().default(0), createdAt: text('created_at').notNull(), }) export const solarSystems = sqliteTable('solar_systems', { id: integer('id').primaryKey({ autoIncrement: true }), saveId: integer('save_id').notNull().references(() => saves.id), name: text('name').notNull(), // 0–100 coordinate space, rendered directly by the NodeGraph component. x: real('x').notNull(), y: real('y').notNull(), discovered: integer('discovered', { mode: 'boolean' }).notNull().default(false), isCurrent: integer('is_current', { mode: 'boolean' }).notNull().default(false), }) // Jump routes, stored as directed pairs (both directions of each route) so adjacency and // "reachable from current" are single-row lookups. Read side dedupes for display. export const jumpRoutes = sqliteTable( 'jump_routes', { fromSystem: integer('from_system').notNull().references(() => solarSystems.id), toSystem: integer('to_system').notNull().references(() => solarSystems.id), }, (t) => [primaryKey({ columns: [t.fromSystem, t.toSystem] })], ) // Bodies of a solar system: planets (parent_id NULL) and moons (parent_id = their planet's // id). Generated when the system is generated, so every system has 2–5 planets, some with // 1–3 moons. Insertion order is display order — a moon always follows its parent row. export const planets = sqliteTable('planets', { id: integer('id').primaryKey({ autoIncrement: true }), systemId: integer('system_id').notNull().references(() => solarSystems.id), parentId: integer('parent_id'), // NULL for a planet, set for a moon name: text('name').notNull(), type: text('type').notNull(), hazard: integer('hazard', { mode: 'boolean' }).notNull().default(false), explored: integer('explored', { mode: 'boolean' }).notNull().default(false), }) // Dumb-simple cargo hold on the save: what exploration has found so far. SHIP SYSTEMS (#8) // will spend parts from here later; nothing consumes it yet. export const inventoryItems = sqliteTable('inventory_items', { id: integer('id').primaryKey({ autoIncrement: true }), saveId: integer('save_id').notNull().references(() => saves.id), kind: text('kind').notNull(), // 'resource' | 'part' name: text('name').notNull(), qty: integer('qty').notNull().default(1), }) // Append-only game log. Writers so far: new-game + jump events; later issues add more // writers and a read endpoint. export const events = sqliteTable('events', { id: integer('id').primaryKey({ autoIncrement: true }), saveId: integer('save_id').notNull().references(() => saves.id), turn: integer('turn').notNull(), type: text('type').notNull(), message: text('message').notNull(), createdAt: text('created_at').notNull(), })