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 { 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";
type Task = InferSelectModel<typeof tasks> & {
type: InferSelectModel<typeof taskTypes>;
};
type TaskOrNull = InferSelectModel<typeof tasks> & {
type: InferSelectModel<typeof taskTypes> | null;
};
class TasksService {
private db: DB;
private caller: "internal" | "api";
@ -10,22 +21,33 @@ class TasksService {
this.caller = caller;
}
public async getAll() {
logger.info("Fetching all task records...");
private async _executeQuery(
query: () => Promise<TaskOrNull[]>,
): Promise<ServiceResponse<Task[], "INTERNAL_ERROR" | "DATA_INTEGRITY_VIOLATION">> {
try {
const tasks = await this.db.query.tasks.findMany({
with: {
type: true,
},
});
logger.debug(`Found ${tasks.length} records.`);
return { tasks, status: "ok" };
const tasks = await query();
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(", ")}`);
return {
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) {
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>) {
const mappedTasks = taskIds.map(x => {
const prefix = x.slice(0, 2);
@ -41,30 +63,22 @@ class TasksService {
: `${taskIds.length} records`
}.`,
);
try {
const tasks = await db.query.tasks.findMany({
return this._executeQuery(() =>
this.db.query.tasks.findMany({
with: { type: true },
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>) {
logger.info(`Fetching ${ids.length} records.`);
try {
const tasks = await db.query.tasks.findMany({
return this._executeQuery(() =>
this.db.query.tasks.findMany({
with: { type: true },
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 };
}
})
);
}
}