Create seeding script.

The script updates task related tables only at this time.

Arguments "seed" and "reset" can be passed. "seed" accepts a flag
"--count" which specifies a custom number of task entries to generate.
"task_types" are currently fixed at TA and PC.

To account for db adapter limitations, the script will automatically
batch databse entries by 500 requests.
This commit is contained in:
themodrnhakr 2025-09-27 14:20:39 -05:00
parent b6c6f74576
commit 5fddf2f394

99
utils/seed.ts Normal file
View File

@ -0,0 +1,99 @@
import { db } from "../src/lib/server/db/db";
import { tasks, taskTypes } from "../src/lib/server/db/schema/tasks";
import { faker } from "@faker-js/faker";
import logger from "../src/lib/server/logger";
async function resetDatabase() {
logger.info("Resetting database...");
// Delete in reverse order of creation to respect foreign key constraints
await db.delete(tasks);
await db.delete(taskTypes);
logger.info("Database reset complete.");
}
async function seedDatabase(count: number) {
logger.info(`Seeding database with ${count} tasks...`);
// 1. Seed Task Types
const insertedTaskTypes = await db.insert(taskTypes).values([
{ name: "Product Change", prefix: "PC" },
{ name: "Task", prefix: "TA" },
]).returning();
logger.info(`Seeded ${insertedTaskTypes.length} task types.`);
if (insertedTaskTypes.length === 0) {
throw new Error("Task type seeding failed. Cannot seed tasks.");
}
// 2. Seed Tasks
const newTasks = [];
const usedTaskIds = new Set<number>();
for (let i = 0; i < count; i++) {
let randomId: number;
do {
randomId = Math.floor(100000 + Math.random() * 900000);
} while (usedTaskIds.has(randomId));
usedTaskIds.add(randomId);
newTasks.push({
// task_id with a guaranteed unique 6 digit number
taskId: randomId.toString(),
// a random phrase in each description
description: faker.lorem.sentence(),
// open_date with a valid date
openDate: faker.date.recent({ days: 30 }).toISOString(),
// a random paragraph in body
body: faker.lorem.paragraphs(3),
// other fields as needed
type: faker.helpers.arrayElement(insertedTaskTypes).id,
status: faker.helpers.arrayElement(["Todo", "In Progress", "Done", "Canceled"]),
priority: faker.helpers.arrayElement(["Low", "Medium", "High", "Urgent"]),
});
}
// 3. Insert the new tasks in chunks to avoid exceeding driver limits
logger.info(`Inserting ${newTasks.length} tasks in chunks...`);
const chunkSize = 500;
let totalInserted = 0;
for (let i = 0; i < newTasks.length; i += chunkSize) {
const chunk = newTasks.slice(i, i + chunkSize);
const inserted = await db.insert(tasks).values(chunk).returning();
totalInserted += inserted.length;
logger.info(` ... inserted chunk ${Math.floor(i / chunkSize) + 1}, ${totalInserted}/${newTasks.length} tasks`);
}
logger.info(`Seeding complete. Total tasks inserted: ${totalInserted}.`);
}
async function main() {
const mode = process.argv[2];
// Default count if no flag is provided
let count = 20;
// Find and parse the --count flag
const countArg = process.argv.find((arg) => arg.startsWith("--count="));
if (countArg) {
const countValue = parseInt(countArg.split("=")[1], 10);
if (!isNaN(countValue) && countValue > 0) {
count = countValue;
}
}
if (mode === "reset") {
await resetDatabase();
} else if (mode === "seed") {
// Seeding implies a reset first for a clean slate
await resetDatabase();
await seedDatabase(count);
} else {
logger.error('Invalid mode. Use "seed" or "reset".');
process.exit(1);
}
logger.info("Script finished.");
}
main().catch((e) => {
logger.error(e, "An error occurred during the script execution.");
process.exit(1);
});