All files / web/src/db/schema users.ts

100% Statements 40/40
100% Branches 2/2
100% Functions 0/0
100% Lines 40/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 412x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x  
import { createId } from '@paralleldrive/cuid2'
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core'
 
/**
 * Users table - stores both guest and authenticated users
 *
 * Guest users are created automatically on first visit via middleware.
 * They can upgrade to full accounts later while preserving their data.
 */
export const users = sqliteTable('users', {
  id: text('id')
    .primaryKey()
    .$defaultFn(() => createId()),
 
  /** Stable guest ID from HttpOnly cookie - unique per browser session */
  guestId: text('guest_id').notNull().unique(),
 
  /** When this user record was created */
  createdAt: integer('created_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date()),
 
  /** When guest upgraded to full account (null for guests) */
  upgradedAt: integer('upgraded_at', { mode: 'timestamp' }),
 
  /** Email (only set after upgrade) */
  email: text('email').unique(),
 
  /** Display name (only set after upgrade) */
  name: text('name'),
 
  /** Profile photo URL (from Google OAuth) */
  image: text('image'),
 
  /** User role for authorization: 'user' (default) or 'admin' */
  role: text('role').notNull().default('user'),
})
 
export type User = typeof users.$inferSelect
export type NewUser = typeof users.$inferInsert