Commit7a945a7unknown_key
fix(follows): drop column-by-column user projection so the type tracks live schema
fix(follows): drop column-by-column user projection so the type tracks live schema
L1 (Sleep Mode) added users.sleepModeEnabled + users.sleepModeDigestHourUtc.
M2 (mobile push) added users.notifyPushOn{Mention,Assign,ReviewRequest,DeployFailed}.
`listFollowers` and `listFollowing` were enumerating user columns by name in
`db.select({...})` and lost those 6 columns. The function signature
(`Promise<User[]>`) demanded the full row shape, so tsc fired TS2322 on
both call sites.
Switch to `db.select().from(users).innerJoin(userFollows, ...)` which makes
drizzle infer the row type from the live schema. The join order flips so
the user row is the primary `from()` and gets returned as `r.users` from
the join result.
`bunx tsc --noEmit` is now clean. Suite remains 1651 / 0 fail / 2 skip.1 file changed+14−407a945a72f2286289b067527ba65362354d6db066
1 changed file+14−40
Modifiedsrc/lib/follows.ts+14−40View fileUnifiedSplit
@@ -77,53 +77,27 @@ export async function isFollowing(
7777// ----------------------------------------------------------------------------
7878
7979export async function listFollowers(userId: string): Promise<User[]> {
80 // Use `db.select().from(users)` (no projection) so the returned type
81 // tracks the live `users` schema. L1 (Sleep Mode) + M2 (push prefs)
82 // added 6 new columns; enumerating column-by-column made this list
83 // drift out of sync.
8084 return db
81 .select({
82 id: users.id,
83 username: users.username,
84 email: users.email,
85 displayName: users.displayName,
86 passwordHash: users.passwordHash,
87 avatarUrl: users.avatarUrl,
88 bio: users.bio,
89 notifyEmailOnMention: users.notifyEmailOnMention,
90 notifyEmailOnAssign: users.notifyEmailOnAssign,
91 notifyEmailOnGateFail: users.notifyEmailOnGateFail,
92 notifyEmailDigestWeekly: users.notifyEmailDigestWeekly,
93 lastDigestSentAt: users.lastDigestSentAt,
94 isAdmin: users.isAdmin,
95 createdAt: users.createdAt,
96 updatedAt: users.updatedAt,
97 })
98 .from(userFollows)
99 .innerJoin(users, eq(userFollows.followerId, users.id))
85 .select()
86 .from(users)
87 .innerJoin(userFollows, eq(userFollows.followerId, users.id))
10088 .where(eq(userFollows.followingId, userId))
101 .orderBy(desc(userFollows.createdAt));
89 .orderBy(desc(userFollows.createdAt))
90 .then((rows) => rows.map((r) => r.users));
10291}
10392
10493export async function listFollowing(userId: string): Promise<User[]> {
10594 return db
106 .select({
107 id: users.id,
108 username: users.username,
109 email: users.email,
110 displayName: users.displayName,
111 passwordHash: users.passwordHash,
112 avatarUrl: users.avatarUrl,
113 bio: users.bio,
114 notifyEmailOnMention: users.notifyEmailOnMention,
115 notifyEmailOnAssign: users.notifyEmailOnAssign,
116 notifyEmailOnGateFail: users.notifyEmailOnGateFail,
117 notifyEmailDigestWeekly: users.notifyEmailDigestWeekly,
118 lastDigestSentAt: users.lastDigestSentAt,
119 isAdmin: users.isAdmin,
120 createdAt: users.createdAt,
121 updatedAt: users.updatedAt,
122 })
123 .from(userFollows)
124 .innerJoin(users, eq(userFollows.followingId, users.id))
95 .select()
96 .from(users)
97 .innerJoin(userFollows, eq(userFollows.followingId, users.id))
12598 .where(eq(userFollows.followerId, userId))
126 .orderBy(desc(userFollows.createdAt));
99 .orderBy(desc(userFollows.createdAt))
100 .then((rows) => rows.map((r) => r.users));
127101}
128102
129103export async function followCounts(userId: string): Promise<{
130104