"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.taskQuerySchema = exports.syncQuerySchema = exports.pushChangesSchema = exports.tombstoneSchema = exports.friendshipSchema = exports.friendRequestSchema = exports.searchQuerySchema = exports.repeatProfileUpdateSchema = exports.repeatProfileSchema = exports.userSettingsSchema = exports.subtaskUpdateSchema = exports.subtaskCreateSchema = exports.taskUpdateSchema = exports.taskCreateSchema = exports.repeatIntervalFieldSchema = exports.repeatFieldSchema = exports.repeatSchema = exports.categoryUpdateSchema = exports.categoryCreateSchema = void 0; exports.canCompleteTask = canCompleteTask; const zod_1 = require("zod"); function canCompleteTask(dueDate) { if (dueDate === 0) return true; const now = new Date(); const endOfToday = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 23, 59, 59, 999).getTime(); return dueDate <= endOfToday; } exports.categoryCreateSchema = zod_1.z.object({ name: zod_1.z.string().min(1).max(50), color: zod_1.z.string().regex(/^#[0-9A-Fa-f]{6}$/), order: zod_1.z.number().int().min(0).optional(), }); exports.categoryUpdateSchema = zod_1.z.object({ name: zod_1.z.string().min(1).max(50).optional(), color: zod_1.z.string().regex(/^#[0-9A-Fa-f]{6}$/).optional(), order: zod_1.z.number().int().min(0).optional(), }); exports.repeatSchema = zod_1.z.enum(['none', 'daily', 'weekly', 'monthly', 'custom']); // The client stores '' / 0 for unset repeat values; normalize them so stale or // legacy rows never fail validation on push. exports.repeatFieldSchema = exports.repeatSchema .or(zod_1.z.literal('')) .transform((v) => (v === '' ? 'none' : v)) .optional(); exports.repeatIntervalFieldSchema = zod_1.z .number() .int() .min(0) .max(30) .transform((v) => Math.max(1, v)) .optional(); exports.taskCreateSchema = zod_1.z.object({ title: zod_1.z.string().min(1).max(100), description: zod_1.z.string().max(1000).optional(), categoryId: zod_1.z.string().max(100).transform((v) => (v === '' ? null : v)).nullable(), priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(), dueDate: zod_1.z.number().int().min(0).optional(), dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''), endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')), allDay: zod_1.z.boolean().optional(), repeat: exports.repeatFieldSchema, repeatInterval: exports.repeatIntervalFieldSchema, repeatDays: zod_1.z.string().max(20).optional(), seriesId: zod_1.z.string().max(50).optional(), reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(), reminders: zod_1.z.string().max(100).optional(), assigneeId: zod_1.z.string().nullable().optional(), completedAt: zod_1.z.number().int().min(0).nullable().optional(), subtasks: zod_1.z.array(zod_1.z.object({ title: zod_1.z.string().min(1).max(100) })).optional(), }); exports.taskUpdateSchema = zod_1.z.object({ title: zod_1.z.string().min(1).max(100).optional(), description: zod_1.z.string().max(1000).optional(), categoryId: zod_1.z.string().max(100).nullable().optional().transform((v) => (v === '' ? null : v)), priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(), completed: zod_1.z.boolean().optional(), dueDate: zod_1.z.number().int().min(0).optional(), dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v), endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(), reminders: zod_1.z.string().max(100).optional(), assigneeId: zod_1.z.string().nullable().optional(), completedAt: zod_1.z.number().int().min(0).nullable().optional(), }); exports.subtaskCreateSchema = zod_1.z.object({ title: zod_1.z.string().min(1).max(100), description: zod_1.z.string().max(1000).optional(), priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(), dueDate: zod_1.z.number().int().min(0).optional(), dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v ?? ''), endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')), allDay: zod_1.z.boolean().optional(), repeat: exports.repeatFieldSchema, repeatInterval: exports.repeatIntervalFieldSchema, repeatDays: zod_1.z.string().max(20).optional(), seriesId: zod_1.z.string().max(50).optional(), reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(), reminders: zod_1.z.string().max(100).optional(), assigneeId: zod_1.z.string().nullable().optional(), order: zod_1.z.number().int().min(0).optional(), parentSubtaskId: zod_1.z.string().nullable().optional(), }); exports.subtaskUpdateSchema = zod_1.z.object({ title: zod_1.z.string().min(1).max(100).optional(), description: zod_1.z.string().max(1000).optional(), priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(), completed: zod_1.z.boolean().optional(), dueDate: zod_1.z.number().int().min(0).optional(), dueTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().or(zod_1.z.literal('')).transform(v => v === '' ? undefined : v), endTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(), allDay: zod_1.z.boolean().optional(), repeat: exports.repeatFieldSchema, repeatInterval: exports.repeatIntervalFieldSchema, repeatDays: zod_1.z.string().max(20).optional(), seriesId: zod_1.z.string().max(50).optional(), reminder: zod_1.z.enum(['none', 'at_time', '15', '30', '60', '120', '1440']).optional(), reminders: zod_1.z.string().max(100).optional(), assigneeId: zod_1.z.string().nullable().optional(), order: zod_1.z.number().int().min(0).optional(), parentSubtaskId: zod_1.z.string().nullable().optional(), }); exports.userSettingsSchema = zod_1.z.object({ darkMode: zod_1.z.boolean().optional(), notifications: zod_1.z.boolean().optional(), reminderTime: zod_1.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional(), defaultCategory: zod_1.z.string().optional().nullable(), sortBy: zod_1.z.enum(['dueDate', 'priority', 'title', 'createdAt']).optional(), sortOrder: zod_1.z.enum(['asc', 'desc']).optional(), }); exports.repeatProfileSchema = zod_1.z.object({ name: zod_1.z.string().min(1).max(50), repeat: exports.repeatSchema, repeatInterval: zod_1.z.number().int().min(1).max(30), repeatDays: zod_1.z.string().max(20), }); exports.repeatProfileUpdateSchema = zod_1.z.object({ name: zod_1.z.string().min(1).max(50).optional(), repeat: exports.repeatSchema.optional(), repeatInterval: zod_1.z.number().int().min(1).max(30).optional(), repeatDays: zod_1.z.string().max(20).optional(), }); exports.searchQuerySchema = zod_1.z.object({ q: zod_1.z.string().min(1).max(50), }); exports.friendRequestSchema = zod_1.z.object({ username: zod_1.z.string().min(1).max(50), }); exports.friendshipSchema = zod_1.z.object({ id: zod_1.z.string(), userId: zod_1.z.string(), friendId: zod_1.z.string(), status: zod_1.z.enum(['pending', 'accepted']), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number(), }); exports.tombstoneSchema = zod_1.z.object({ entity: zod_1.z.enum(['categories', 'tasks', 'subtasks', 'repeatProfiles', 'friendships']), id: zod_1.z.string(), updatedAt: zod_1.z.number().int().min(0), }); exports.pushChangesSchema = zod_1.z.object({ changes: zod_1.z.object({ categories: zod_1.z.array(exports.categoryCreateSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(), tasks: zod_1.z.array(exports.taskCreateSchema.extend({ id: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number(), completedAt: zod_1.z.number().int().min(0).nullable().optional() })).optional(), subtasks: zod_1.z.array(exports.subtaskCreateSchema.extend({ id: zod_1.z.string(), taskId: zod_1.z.string(), completed: zod_1.z.boolean(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(), repeatProfiles: zod_1.z.array(exports.repeatProfileSchema.extend({ id: zod_1.z.string(), createdAt: zod_1.z.number(), updatedAt: zod_1.z.number() })).optional(), friendships: zod_1.z.array(exports.friendshipSchema).optional(), }), deleted: zod_1.z.array(exports.tombstoneSchema).optional(), lastPulledAt: zod_1.z.number().int().min(0), }); exports.syncQuerySchema = zod_1.z.object({ since: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)), }); exports.taskQuerySchema = zod_1.z.object({ categoryId: zod_1.z.string().optional(), completed: zod_1.z.string().transform(v => v === 'true').optional(), dueBefore: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(), dueAfter: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(), priority: zod_1.z.enum(['none', 'low', 'medium', 'high', 'critical']).optional(), sortBy: zod_1.z.enum(['dueDate', 'priority', 'createdAt', 'title']).optional(), sortOrder: zod_1.z.enum(['asc', 'desc']).optional(), limit: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(1).max(100)).optional(), offset: zod_1.z.string().transform(Number).pipe(zod_1.z.number().int().min(0)).optional(), }); //# sourceMappingURL=validation.js.map