From ed4e64a06ae4f81cf63fa31ccc5aa43a87da90ff Mon Sep 17 00:00:00 2001 From: Lucas Berger Date: Mon, 15 Jun 2026 16:25:05 -0400 Subject: [PATCH] fix(12): WR-02 fix TypeScript type annotation for execute() count result Drizzle mysql2 execute() returns [rows, fields] for SELECT queries; the generic type parameter alone does not correctly type the result. Use unknown cast pattern consistent with admin.ts to access the count row. Co-Authored-By: Claude Sonnet 4.6 --- apps/api/src/routes/setup.ts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/api/src/routes/setup.ts b/apps/api/src/routes/setup.ts index 63bc98d..13795e5 100644 --- a/apps/api/src/routes/setup.ts +++ b/apps/api/src/routes/setup.ts @@ -255,11 +255,14 @@ setupRouter.post('/credential', zValidator('json', credentialSchema, noEchoHook) let localUser: typeof users.$inferSelect | undefined; try { localUser = await db.transaction(async (tx) => { - // Serialise: at most one unclaimed admin row may exist (WR-02) - const [{ count }] = await tx.execute<{ count: number }>( + // Serialise: at most one unclaimed admin row may exist (WR-02). + // Cast through unknown — Drizzle mysql2 execute() returns [rows, fields] for SELECTs; + // the generic type parameter on execute() is not sufficient to type the result correctly. + const countRows = (await tx.execute( sql`SELECT COUNT(*) AS count FROM users WHERE claimed = false FOR UPDATE`, - ); - if (Number(count) > 0) { + )) as unknown as [{ count: string | number }[], unknown]; + const unclaimedCount = Number(countRows[0][0]?.count ?? 0); + if (unclaimedCount > 0) { throw Object.assign(new Error('An unclaimed user already exists'), { code: 'DUPLICATE_UNCLAIMED' }); }