2.0.0
All checks were successful
Docker Deploy / build-and-push (push) Successful in 3m49s

This commit is contained in:
2026-01-18 14:27:47 -07:00
parent ce47de9e56
commit 5e70dd6bb8
8 changed files with 217 additions and 163 deletions

83
src/lib/validation.ts Normal file
View File

@@ -0,0 +1,83 @@
import { db } from "../db";
import { clients, categories, tags as tagsTable } from "../db/schema";
import { eq, and, inArray } from "drizzle-orm";
export async function validateTimeEntryResources({
organizationId,
clientId,
categoryId,
tagIds,
}: {
organizationId: string;
clientId: string;
categoryId: string;
tagIds?: string[];
}) {
const [client, category] = await Promise.all([
db
.select()
.from(clients)
.where(
and(
eq(clients.id, clientId),
eq(clients.organizationId, organizationId),
),
)
.get(),
db
.select()
.from(categories)
.where(
and(
eq(categories.id, categoryId),
eq(categories.organizationId, organizationId),
),
)
.get(),
]);
if (!client) {
return { valid: false, error: "Invalid client" };
}
if (!category) {
return { valid: false, error: "Invalid category" };
}
if (tagIds && tagIds.length > 0) {
const validTags = await db
.select()
.from(tagsTable)
.where(
and(
inArray(tagsTable.id, tagIds),
eq(tagsTable.organizationId, organizationId),
),
)
.all();
if (validTags.length !== tagIds.length) {
return { valid: false, error: "Invalid tags" };
}
}
return { valid: true };
}
export function validateTimeRange(
start: string | number | Date,
end: string | number | Date,
) {
const startDate = new Date(start);
const endDate = new Date(end);
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) {
return { valid: false, error: "Invalid date format" };
}
if (endDate <= startDate) {
return { valid: false, error: "End time must be after start time" };
}
return { valid: true, startDate, endDate };
}