Phase 12: Initial Setup Wizard #22

Merged
luckberg merged 76 commits from gsd/phase-12-initial-setup-wizard into main 2026-06-16 19:10:33 -04:00
Showing only changes of commit ed4e64a06a - Show all commits
+7 -4
View File
@@ -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' });
}