place_maxlan/shared/schema.ts
freesemar93 de5e7bfc6c Add basic structure for a collaborative pixel art website
Adds the core project structure, including configuration files, a basic HTML page, and the main application component. It also lays the groundwork for the canvas, color palette, and configuration modal functionalities.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 0385ea33-cde8-4bbd-8fce-8d192d30eb41
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/870d08ce-da3b-4822-9874-c2fe2b7628b1/0385ea33-cde8-4bbd-8fce-8d192d30eb41/Vuy7IOw
2025-08-18 12:13:30 +00:00

90 lines
3.0 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
showGridByDefault: boolean("show_grid_by_default").notNull().default(true),
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("config_updated"),
data: insertCanvasConfigSchema,
}),
z.object({
type: z.literal("cooldown_update"),
data: z.object({
userId: z.string(),
remainingSeconds: z.number(),
}),
}),
]);
export type WSMessage = z.infer<typeof wsMessageSchema>;