I'm trying to seed a user into the database during my setup process

Is there a way to seed a user directly into the database using Better Auth without relying on the request context(cookies)? const superAdminResult = await auth.api.signUpEmail({ body: { email: "admin@example.com", password: "kjk2nduhu23dsa2", name: "ADMIN", } })
12 Replies
Spipov
Spipov3mo ago
Its a massive pita. You need to figure out password hashing using argon2 and scrypt. Im honestly recommending scripting to make 1st user register, or otp or somethinf
Omar-7ioo
Omar-7ioo3mo ago
You could create a seed script using your ORM and setup GitHub actions.
The Untraceable
The Untraceable3mo ago
I personally use auth.api.admin.createUser iirc. Give that a try
Omar-7ioo
Omar-7ioo3mo ago
This is how I handled seeding for my use case
// --- Check for Admin User ---
const [existingAdminUser] = await db
.select({ userId: schema.user.id })
.from(schema.user)
.where(eq(schema.user.username, "admin"));

if (existingAdminUser?.userId) {
console.log("✅ Admin user already exists.");
} else {
console.log("Creating admin user...");
const { user: admin } = await betterAuth.api.createUser({
body: {
role: "admin",
name: "Admin User",
email: env.ADMIN_EMAIL,
password: env.ADMIN_PASSWORD,
},
});

if (!admin?.id) {
console.error("❌ Failed to create admin user.");
shouldExit = true; // Mark for exit later
} else {
await db
.update(schema.user)
.set({ username: "admin" })
.where(eq(schema.user.id, admin.id));
console.log("✅ Admin user created.");
}
}
// --- Check for Admin User ---
const [existingAdminUser] = await db
.select({ userId: schema.user.id })
.from(schema.user)
.where(eq(schema.user.username, "admin"));

if (existingAdminUser?.userId) {
console.log("✅ Admin user already exists.");
} else {
console.log("Creating admin user...");
const { user: admin } = await betterAuth.api.createUser({
body: {
role: "admin",
name: "Admin User",
email: env.ADMIN_EMAIL,
password: env.ADMIN_PASSWORD,
},
});

if (!admin?.id) {
console.error("❌ Failed to create admin user.");
shouldExit = true; // Mark for exit later
} else {
await db
.update(schema.user)
.set({ username: "admin" })
.where(eq(schema.user.id, admin.id));
console.log("✅ Admin user created.");
}
}
Budi
Budi3mo ago
Can you do this if there's no admin user in the database? So when you're starting from 0 users?
The Untraceable
The Untraceable3mo ago
yup, that's what i do to create the first user
The Untraceable
The Untraceable3mo ago
/** biome-ignore-all lint/suspicious/noConsole: Console logs in CLI tools are acceptable */

import { auth } from '@/lib/auth';
import { registerSchema } from '@/schemas/auth';
import prompts from 'prompts';

(async () => {
const response = await prompts(
[
{
type: 'text',
name: 'email',
message: 'Enter admin email',
},
{
type: 'text',
name: 'name',
message: 'Enter admin name',
},
{
type: 'password',
name: 'password',
message: 'Enter admin password',
},
{
type: 'password',
name: 'confirmPassword',
message: 'Confirm admin password',
},
],
{
onCancel: () => {
console.log('Admin creation cancelled.');
process.exit(0);
},
}
);

if (response.password !== response.confirmPassword) {
console.error('Passwords do not match.');
process.exit(1);
}

const parsed = registerSchema.safeParse(response);
if (!parsed.success) {
for (const error of parsed.error.errors) {
console.error(`Validation error: ${error.message}`);
}
process.exit(1);
}

try {
const createUserResponse = await auth.api.createUser({
body: {
email: parsed.data.email,
password: parsed.data.password,
name: parsed.data.name,
role: 'admin',
},
});

if (createUserResponse.user) {
console.log(
`Admin user created successfully: ${createUserResponse.user.email} `
);
process.exit(0);
}
} catch (error) {
if (error instanceof Error) {
console.error(`An unexpected error occurred: ${error.message}`);
} else {
console.error('An unexpected error occurred.');
}
process.exit(1);
}
})();
/** biome-ignore-all lint/suspicious/noConsole: Console logs in CLI tools are acceptable */

import { auth } from '@/lib/auth';
import { registerSchema } from '@/schemas/auth';
import prompts from 'prompts';

(async () => {
const response = await prompts(
[
{
type: 'text',
name: 'email',
message: 'Enter admin email',
},
{
type: 'text',
name: 'name',
message: 'Enter admin name',
},
{
type: 'password',
name: 'password',
message: 'Enter admin password',
},
{
type: 'password',
name: 'confirmPassword',
message: 'Confirm admin password',
},
],
{
onCancel: () => {
console.log('Admin creation cancelled.');
process.exit(0);
},
}
);

if (response.password !== response.confirmPassword) {
console.error('Passwords do not match.');
process.exit(1);
}

const parsed = registerSchema.safeParse(response);
if (!parsed.success) {
for (const error of parsed.error.errors) {
console.error(`Validation error: ${error.message}`);
}
process.exit(1);
}

try {
const createUserResponse = await auth.api.createUser({
body: {
email: parsed.data.email,
password: parsed.data.password,
name: parsed.data.name,
role: 'admin',
},
});

if (createUserResponse.user) {
console.log(
`Admin user created successfully: ${createUserResponse.user.email} `
);
process.exit(0);
}
} catch (error) {
if (error instanceof Error) {
console.error(`An unexpected error occurred: ${error.message}`);
} else {
console.error('An unexpected error occurred.');
}
process.exit(1);
}
})();
Here's my code, works just fine for me.
No description
The Untraceable
The Untraceable3mo ago
Doesn't require the auth server to be online
Budi
Budi3mo ago
Awesome thank you for sharing this. How do you get access to the createUser API call? Is that because you have the admin plugin installed?
The Untraceable
The Untraceable3mo ago
Yup Makes it super easy
Budi
Budi3mo ago
Terrific I'm going to try this. You're awesome.
d3adb0y
d3adb0y2mo ago
im seeing Property 'createUser' does not exist on type when I try and access it. What am I doing wrong? nevermind im a goober, figured it out

Did you find this page helpful?