import { pgTable, uuid, text, integer, smallint, timestamp, primaryKey } from "drizzle-orm/pg-core"; // One row per registered MC server. Phase 1 has no admin registration API yet (Phase 6) — // rows are created by `bun run seed` from MCMAPPER_SEED_SERVER_NAME/_TOKEN env vars. export const servers = pgTable("servers", { id: uuid("id").defaultRandom().primaryKey(), name: text("name").notNull(), token: text("token").notNull().unique(), authMode: text("auth_mode").notNull().default("offline"), createdAt: timestamp("created_at", { withTimezone: true }).notNull().defaultNow(), }); // Column-granularity world state: the topmost non-air block per (dimension, x, z), plus its // height. This is deliberately not full per-voxel storage — Phase 1 only needs enough to // rasterize a top-down 2D tile and to derive marker Y later. Full block/section data for 3D // meshing is a Phase 2 extension of this table, not built now (see plan's phased scope). export const chunkColumns = pgTable( "chunk_columns", { serverId: uuid("server_id") .notNull() .references(() => servers.id, { onDelete: "cascade" }), dimension: integer("dimension").notNull(), x: integer("x").notNull(), z: integer("z").notNull(), blockId: integer("block_id").notNull(), blockMeta: integer("block_meta").notNull(), height: smallint("height").notNull(), updatedAt: timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => [primaryKey({ columns: [table.serverId, table.dimension, table.x, table.z] })], ); // Metadata pointer to a rendered tile PNG in MinIO — the binary itself never touches Postgres. // One row per (server, dimension, zoom, tileX, tileZ); zoom is always 0 until Phase 2 adds // multi-resolution tiles. export const tilePointers = pgTable( "tile_pointers", { serverId: uuid("server_id") .notNull() .references(() => servers.id, { onDelete: "cascade" }), dimension: integer("dimension").notNull(), zoom: integer("zoom").notNull().default(0), tileX: integer("tile_x").notNull(), tileZ: integer("tile_z").notNull(), storageKey: text("storage_key").notNull(), contentHash: text("content_hash").notNull(), renderedAt: timestamp("rendered_at", { withTimezone: true }).notNull().defaultNow(), }, (table) => [ primaryKey({ columns: [table.serverId, table.dimension, table.zoom, table.tileX, table.tileZ] }), ], );