Improve typing and internal abstraction.

The only breaking change here is the 'tasks' field is now 'data'. All
other changes were made to improve TypeScripts ability to infer complex
types or internal abstractions that don't affect client consumption.
This commit is contained in:
themodrnhakr 2025-09-29 21:13:26 -05:00
parent 0990cf5c56
commit 5bc27f6061

View File

@ -1,6 +1,17 @@
import { type DB, db } from "$lib/server/db/db"; import { type DB, db } from "$lib/server/db/db";
import type { tasks, taskTypes } from "$lib/server/db/schema/tasks";
import type { ServiceResponse } from "$lib/server/services/service.types";
import type { InferSelectModel } from "drizzle-orm";
import logger from "../logger"; import logger from "../logger";
type Task = InferSelectModel<typeof tasks> & {
type: InferSelectModel<typeof taskTypes>;
};
type TaskOrNull = InferSelectModel<typeof tasks> & {
type: InferSelectModel<typeof taskTypes> | null;
};
class TasksService { class TasksService {
private db: DB; private db: DB;
private caller: "internal" | "api"; private caller: "internal" | "api";
@ -10,22 +21,33 @@ class TasksService {
this.caller = caller; this.caller = caller;
} }
public async getAll() { private async _executeQuery(
logger.info("Fetching all task records..."); query: () => Promise<TaskOrNull[]>,
): Promise<ServiceResponse<Task[], "INTERNAL_ERROR" | "DATA_INTEGRITY_VIOLATION">> {
try { try {
const tasks = await this.db.query.tasks.findMany({ const tasks = await query();
with: {
type: true, if (tasks.some(x => x.type === null)) {
}, const badTaskIds = tasks.filter(t => t.type === null).map(t => t.id);
}); logger.error(`Data integrity issue: The following tasks have invalid type IDs: ${badTaskIds.join(", ")}`);
logger.debug(`Found ${tasks.length} records.`); return {
return { tasks, status: "ok" }; status: "failure",
error: "One or more tasks are invalid because they are not associated with a type.",
code: "DATA_INTEGRITY_VIOLATION",
};
}
return { data: tasks as Task[], status: "ok" };
} catch (error) { } catch (error) {
logger.error({ msg: "Error querying the database.", error }); logger.error({ msg: "Error querying the database.", error });
return { status: "failed", error }; return { status: "failure", error: "An internal server error occurred.", code: "INTERNAL_ERROR" };
} }
} }
public async getAll() {
logger.info("Fetching all task records...");
return this._executeQuery(() => this.db.query.tasks.findMany({ with: { type: true } }));
}
public async getByTaskId(taskIds: Array<string>) { public async getByTaskId(taskIds: Array<string>) {
const mappedTasks = taskIds.map(x => { const mappedTasks = taskIds.map(x => {
const prefix = x.slice(0, 2); const prefix = x.slice(0, 2);
@ -41,30 +63,22 @@ class TasksService {
: `${taskIds.length} records` : `${taskIds.length} records`
}.`, }.`,
); );
try { return this._executeQuery(() =>
const tasks = await db.query.tasks.findMany({ this.db.query.tasks.findMany({
with: { type: true }, with: { type: true },
where: (tasks, { inArray }) => inArray(tasks.taskId, mappedTasks.map(x => x.task_id)), where: (tasks, { inArray }) => inArray(tasks.taskId, mappedTasks.map(x => x.task_id)),
}); })
return { tasks, status: "ok" }; );
} catch (error) {
logger.error({ msg: "Error querying the database.", error });
return { status: "failed", error };
}
} }
public async getByDbId(ids: Array<number>) { public async getByDbId(ids: Array<number>) {
logger.info(`Fetching ${ids.length} records.`); logger.info(`Fetching ${ids.length} records.`);
try { return this._executeQuery(() =>
const tasks = await db.query.tasks.findMany({ this.db.query.tasks.findMany({
with: { type: true }, with: { type: true },
where: (tasks, { inArray }) => inArray(tasks.id, ids), where: (tasks, { inArray }) => inArray(tasks.id, ids),
}); })
return { tasks, status: "ok" }; );
} catch (error) {
logger.error({ msg: "Error querying the database.", error });
return { status: "failed", error };
}
} }
} }