import { pgTable, timestamp, uuid, varchar, text, boolean, integer, jsonb, unique } from 'drizzle-orm/pg-core'; export const users = pgTable('users', { id: uuid('id').defaultRandom().primaryKey(), email: varchar('email', { length: 255 }).notNull().unique(), name: varchar('name', { length: 255 }).notNull(), passwordHash: varchar('password_hash', { length: 255 }).notNull(), emailVerified: boolean('email_verified').default(false).notNull(), image: text('image'), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const devices = pgTable('devices', { id: uuid('id').defaultRandom().primaryKey(), userId: uuid('user_id').notNull().references(() => users.id), name: varchar('name', { length: 255 }), role: varchar('role', { length: 32 }).default('client').notNull(), platform: varchar('platform', { length: 32 }), appVersion: varchar('app_version', { length: 64 }), pushToken: text('push_token'), status: varchar('status', { length: 32 }).default('offline').notNull(), isCamera: boolean('is_camera').default(false).notNull(), lastSeenAt: timestamp('last_seen_at', { withTimezone: true }), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), }); export const deviceLinks = pgTable( 'device_links', { id: uuid('id').defaultRandom().primaryKey(), ownerUserId: uuid('owner_user_id').notNull().references(() => users.id), cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id), clientDeviceId: uuid('client_device_id').notNull().references(() => devices.id), status: varchar('status', { length: 32 }).default('active').notNull(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }, (table) => ({ uniqueDevicePair: unique('device_links_camera_client_unique').on(table.cameraDeviceId, table.clientDeviceId), }), ); export const deviceCommands = pgTable('device_commands', { id: uuid('id').defaultRandom().primaryKey(), ownerUserId: uuid('owner_user_id').notNull().references(() => users.id), sourceDeviceId: uuid('source_device_id').notNull().references(() => devices.id), targetDeviceId: uuid('target_device_id').notNull().references(() => devices.id), commandType: varchar('command_type', { length: 64 }).notNull(), payload: jsonb('payload').$type | null>().default(null), status: varchar('status', { length: 32 }).default('queued').notNull(), retryCount: integer('retry_count').default(0).notNull(), lastDispatchedAt: timestamp('last_dispatched_at', { withTimezone: true }), acknowledgedAt: timestamp('acknowledged_at', { withTimezone: true }), error: text('error'), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const streamSessions = pgTable('stream_sessions', { id: uuid('id').defaultRandom().primaryKey(), ownerUserId: uuid('owner_user_id').notNull().references(() => users.id), cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id), requesterDeviceId: uuid('requester_device_id').notNull().references(() => devices.id), status: varchar('status', { length: 32 }).default('requested').notNull(), reason: varchar('reason', { length: 32 }).default('on_demand').notNull(), streamKey: varchar('stream_key', { length: 255 }), startedAt: timestamp('started_at', { withTimezone: true }), endedAt: timestamp('ended_at', { withTimezone: true }), metadata: jsonb('metadata').$type | null>().default(null), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const events = pgTable('events', { id: uuid('id').defaultRandom().primaryKey(), userId: uuid('user_id').notNull().references(() => users.id), deviceId: uuid('device_id').references(() => devices.id), title: varchar('title', { length: 255 }), triggeredBy: varchar('triggered_by', { length: 64 }).default('motion'), status: varchar('status', { length: 32 }).default('recording').notNull(), startedAt: timestamp('started_at', { withTimezone: true }).notNull(), endedAt: timestamp('ended_at', { withTimezone: true }), notifiedAt: timestamp('notified_at', { withTimezone: true }), videoUrl: varchar('video_url', { length: 1024 }).unique(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const videos = pgTable('videos', { id: uuid('id').defaultRandom().primaryKey(), eventId: uuid('event_id').references(() => events.id), userId: uuid('user_id').notNull().references(() => users.id), deviceId: uuid('device_id').notNull().references(() => devices.id), objectKey: varchar('object_key', { length: 1024 }).notNull().unique(), bucket: varchar('bucket', { length: 255 }).notNull(), uploadUrl: text('upload_url').notNull(), downloadUrl: text('download_url'), status: varchar('status', { length: 32 }).notNull().default('pending'), expiresAt: timestamp('expires_at', { withTimezone: true }), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const notifications = pgTable('notifications', { id: uuid('id').defaultRandom().primaryKey(), eventId: uuid('event_id').references(() => events.id).notNull(), userId: uuid('user_id').references(() => users.id).notNull(), sentAt: timestamp('sent_at', { withTimezone: true }).defaultNow().notNull(), channel: varchar('channel', { length: 32 }).notNull(), status: varchar('status', { length: 32 }).default('queued').notNull(), isRead: boolean('is_read').default(false).notNull(), }); export const accounts = pgTable('account', { id: uuid('id').defaultRandom().primaryKey(), userId: uuid('user_id').notNull().references(() => users.id), accountId: text('account_id').notNull(), providerId: text('provider_id').notNull(), accessToken: text('access_token'), refreshToken: text('refresh_token'), accessTokenExpiresAt: timestamp('access_token_expires_at', { withTimezone: true }), refreshTokenExpiresAt: timestamp('refresh_token_expires_at', { withTimezone: true }), idToken: text('id_token'), scope: text('scope'), password: text('password'), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const sessions = pgTable('session', { id: uuid('id').defaultRandom().primaryKey(), userId: uuid('user_id').notNull().references(() => users.id), token: text('token').notNull().unique(), expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(), ipAddress: text('ip_address'), userAgent: text('user_agent'), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const verifications = pgTable('verification', { id: uuid('id').defaultRandom().primaryKey(), identifier: text('identifier').notNull(), value: text('value').notNull(), expiresAt: timestamp('expires_at', { withTimezone: true }).notNull(), createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(), updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(), }); export const schema = { users, devices, deviceLinks, deviceCommands, streamSessions, events, videos, notifications, accounts, sessions, verifications, };