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

100% Statements 81/81
100% Branches 4/4
100% Functions 3/3
100% Lines 81/81

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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 822x 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 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 39x 39x 39x 39x 39x 39x 2x 2x 2x 2x  
import { createId } from '@paralleldrive/cuid2'
import { integer, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core'
import { users } from './users'
 
/**
 * Households table
 *
 * A household groups multiple users under a single subscription.
 * The owner's subscription covers all household members.
 * Users can belong to multiple households.
 */
export const households = sqliteTable('households', {
  id: text('id')
    .primaryKey()
    .$defaultFn(() => createId()),
 
  /** Display name (e.g. "The Smith Family") */
  name: text('name').notNull(),
 
  /** The billing owner — their subscription covers all members */
  ownerId: text('owner_id')
    .notNull()
    .references(() => users.id, { onDelete: 'cascade' }),
 
  createdAt: integer('created_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date()),
 
  updatedAt: integer('updated_at', { mode: 'timestamp' })
    .notNull()
    .$defaultFn(() => new Date()),
})
 
export type Household = typeof households.$inferSelect
export type NewHousehold = typeof households.$inferInsert
 
/**
 * Household members table
 *
 * Maps users to households with a role (owner or member).
 * A user can belong to multiple households.
 * A user can only appear once per household (unique constraint).
 */
export const householdMembers = sqliteTable(
  'household_members',
  {
    id: text('id')
      .primaryKey()
      .$defaultFn(() => createId()),
 
    /** Which household */
    householdId: text('household_id')
      .notNull()
      .references(() => households.id, { onDelete: 'cascade' }),
 
    /** Which user */
    userId: text('user_id')
      .notNull()
      .references(() => users.id, { onDelete: 'cascade' }),
 
    /** Role within the household */
    role: text('role', { enum: ['owner', 'member'] })
      .notNull()
      .default('member'),
 
    /** When this user joined the household */
    joinedAt: integer('joined_at', { mode: 'timestamp' })
      .notNull()
      .$defaultFn(() => new Date()),
  },
  (table) => ({
    /** A user can only appear once per household */
    householdUserIdx: uniqueIndex('household_members_household_user_idx').on(
      table.householdId,
      table.userId
    ),
  })
)
 
export type HouseholdMember = typeof householdMembers.$inferSelect
export type NewHouseholdMember = typeof householdMembers.$inferInsert