import 'dotenv/config'; import { eq } from 'drizzle-orm'; import { pool } from '../src/lib/server/db/client'; import { db } from '../src/lib/server/db/client'; import { users, companies, companyUsers } from '../src/lib/server/db/schema/tenancy'; import { hashPassword } from '../src/lib/server/auth/password'; import { normalizeEmail } from '../src/lib/utils/email'; function stripSurroundingQuotes(s: string | undefined): string | undefined { if (!s || s.length < 2) return s; const first = s[0]; const last = s[s.length - 1]; if ((first === "'" && last === "'") || (first === '"' && last === '"')) { return s.slice(1, -1); } return s; } function readArg(flag: string, fallback?: string): string | undefined { const i = process.argv.indexOf(flag); return stripSurroundingQuotes(i >= 0 ? process.argv[i + 1] : fallback); } async function main() { const email = readArg('--email'); const password = readArg('--password'); const name = readArg('--name'); const companyName = readArg('--company'); const role = (readArg('--role', 'admin') ?? 'admin') as 'admin' | 'manager' | 'user' | 'viewer'; if (!email || !password || !name) { console.error('Usage: npm run create-user -- --email --password

--name [--company ] [--role admin|manager|user|viewer]'); process.exit(1); } const normalized = normalizeEmail(email); const hash = await hashPassword(password); const [existing] = await db.select().from(users).where(eq(users.emailNormalized, normalized)).limit(1); let userId: string; if (existing) { console.log(`User ${normalized} already exists; updating password.`); await db.update(users).set({ passwordHash: hash, displayName: name }).where(eq(users.id, existing.id)); userId = existing.id; } else { const [created] = await db .insert(users) .values({ email, emailNormalized: normalized, displayName: name, passwordHash: hash }) .returning({ id: users.id }); userId = created.id; console.log(`Created user ${normalized} (id ${userId}).`); } if (companyName) { let [company] = await db.select().from(companies).where(eq(companies.name, companyName)).limit(1); if (!company) { const slug = companyName.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''); const [created] = await db .insert(companies) .values({ name: companyName, slug }) .returning(); company = created; console.log(`Created company ${companyName} (id ${company.id}).`); } const [link] = await db .select() .from(companyUsers) .where(eq(companyUsers.userId, userId)) .limit(1); if (!link || link.companyId !== company.id) { await db .insert(companyUsers) .values({ companyId: company.id, userId, role }) .onConflictDoNothing(); console.log(`Linked user to company ${company.name} as ${role}.`); } } await pool.end(); } main().catch((err) => { console.error(err); process.exit(1); });