place_maxlan/shared/schema.ts
2025-08-21 16:05:29 +02:00

91 lines
3.1 KiB
TypeScript

import { sql } from "drizzle-orm";
import { pgTable, text, varchar, integer, timestamp, boolean, json } from "drizzle-orm/pg-core";
import { createInsertSchema } from "drizzle-zod";
import { z } from "zod";
export const pixels = pgTable("pixels", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
x: integer("x").notNull(),
y: integer("y").notNull(),
color: varchar("color", { length: 7 }).notNull(), // hex color
userId: varchar("user_id").notNull(),
username: varchar("username").notNull(),
createdAt: timestamp("created_at").defaultNow().notNull(),
});
export const canvasConfig = pgTable("canvas_config", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
canvasWidth: integer("canvas_width").notNull().default(100),
canvasHeight: integer("canvas_height").notNull().default(100),
defaultCooldown: integer("default_cooldown").notNull().default(5), // seconds
enableAutomaticEvents: boolean("enable_automatic_events").notNull().default(false),
eventDuration: integer("event_duration").notNull().default(30), // minutes
eventInterval: integer("event_interval").notNull().default(6), // hours
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
export const userCooldowns = pgTable("user_cooldowns", {
id: varchar("id").primaryKey().default(sql`gen_random_uuid()`),
userId: varchar("user_id").notNull(),
lastPlacement: timestamp("last_placement").defaultNow().notNull(),
cooldownEnds: timestamp("cooldown_ends").notNull(),
});
export const insertPixelSchema = createInsertSchema(pixels).omit({
id: true,
createdAt: true,
});
export const insertCanvasConfigSchema = createInsertSchema(canvasConfig).omit({
id: true,
updatedAt: true,
});
export const insertUserCooldownSchema = createInsertSchema(userCooldowns).omit({
id: true,
lastPlacement: true,
});
export type Pixel = typeof pixels.$inferSelect;
export type InsertPixel = z.infer<typeof insertPixelSchema>;
export type CanvasConfig = typeof canvasConfig.$inferSelect;
export type InsertCanvasConfig = z.infer<typeof insertCanvasConfigSchema>;
export type UserCooldown = typeof userCooldowns.$inferSelect;
export type InsertUserCooldown = z.infer<typeof insertUserCooldownSchema>;
// WebSocket message types
export const wsMessageSchema = z.union([
z.object({
type: z.literal("pixel_placed"),
data: z.object({
x: z.number(),
y: z.number(),
color: z.string(),
userId: z.string(),
username: z.string(),
timestamp: z.string(),
}),
}),
z.object({
type: z.literal("user_count"),
data: z.object({
count: z.number(),
}),
}),
z.object({
type: z.literal("cooldown_update"),
data: z.object({
userId: z.string(),
remainingSeconds: z.number(),
}),
}),
]);
export type WSMessage =
| { type: "pixel_placed"; data: { x: number; y: number; color: string; userId: string; username: string; timestamp: string } }
| { type: "user_count"; data: { count: number } }
| { type: "cooldown_update"; data: { userId: string; remainingSeconds: number } }
| { type: "pixel_deleted"; data: { pixelId: string } }
| { type: "canvas_cleared"; data: {} };