diff --git a/package.json b/package.json index b8cc7d8..e56f7d6 100644 --- a/package.json +++ b/package.json @@ -20,31 +20,32 @@ "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-tabs": "^1.1.3", "@radix-ui/react-tooltip": "^1.1.6", + "@schedule-x/calendar": "^2.0.0", + "@schedule-x/drag-and-drop": "^2.0.0", + "@schedule-x/events-service": "^2.0.0", + "@schedule-x/react": "^2.0.0", + "@schedule-x/theme-default": "^2.0.0", + "@tiptap/react": "^2.0.0", + "@tiptap/starter-kit": "^2.0.0", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", + "dompurify": "^3.2.0", + "imapflow": "^1.0.0", "lucide-react": "^0.469.0", + "mailparser": "^3.7.0", "next": "15.1.8", "next-auth": "5.0.0-beta.30", + "nodemailer": "^7.0.0", "react": "19.0.0", "react-dom": "19.0.0", "tailwind-merge": "^2.6.0", "tailwindcss-animate": "^1.0.7", - "zod": "^3.24.1", - "imapflow": "^1.0.0", - "nodemailer": "^7.0.0", - "mailparser": "^3.7.0", "tsdav": "^2.0.0", - "@schedule-x/react": "^2.0.0", - "@schedule-x/calendar": "^2.0.0", - "@schedule-x/events-service": "^2.0.0", - "@schedule-x/drag-and-drop": "^2.0.0", - "@schedule-x/theme-default": "^2.0.0", - "@tiptap/react": "^2.0.0", - "@tiptap/starter-kit": "^2.0.0", - "dompurify": "^3.2.0" + "zod": "^3.24.1" }, "devDependencies": { "@types/dompurify": "^3.2.0", + "@types/mailparser": "^3.4.6", "@types/node": "^22.10.5", "@types/nodemailer": "^6.4.17", "@types/react": "^19.0.4", diff --git a/src/components/calendar/calendar-view.tsx b/src/components/calendar/calendar-view.tsx index b107322..8da39bd 100644 --- a/src/components/calendar/calendar-view.tsx +++ b/src/components/calendar/calendar-view.tsx @@ -134,13 +134,13 @@ export function CalendarView({ try { const currentEvents = eventsPlugin.getAll() - const currentIds = new Set(currentEvents.map((e: { id: string }) => e.id)) - const newIds = new Set(scheduleEvents.map((e) => e.id)) + const currentIds = new Set(currentEvents.map((e) => String(e.id))) + const newIds = new Set(scheduleEvents.map((e) => String(e.id))) // Remove events no longer present - currentEvents.forEach((e: { id: string }) => { - if (!newIds.has(e.id)) { - eventsPlugin.remove(e.id) + currentEvents.forEach((e) => { + if (!newIds.has(String(e.id))) { + eventsPlugin.remove(String(e.id)) } }) diff --git a/src/lib/caldav-client.ts b/src/lib/caldav-client.ts index 292832f..d276600 100644 --- a/src/lib/caldav-client.ts +++ b/src/lib/caldav-client.ts @@ -171,7 +171,7 @@ export async function getCalendars( return calendars.map((cal: DAVCalendar) => ({ url: cal.url, - displayName: cal.displayName || 'Calendar', + displayName: (typeof cal.displayName === 'string' ? cal.displayName : null) || 'Calendar', description: cal.description || undefined, color: (cal as Record).calendarColor as string | undefined, diff --git a/src/lib/imap-client.ts b/src/lib/imap-client.ts index f51b23b..757784f 100644 --- a/src/lib/imap-client.ts +++ b/src/lib/imap-client.ts @@ -110,7 +110,7 @@ export async function listFolders(): Promise { path: mb.path, name: parts[parts.length - 1] || mb.path, delimiter: mb.delimiter || '/', - specialUse: (mb as Record).specialUse as string | null ?? null, + specialUse: (mb as unknown as Record).specialUse as string | null ?? null, subscribed: mb.subscribed ?? false, messages, unseen, @@ -129,7 +129,8 @@ export async function listMessages( return withClient(async (client) => { const lock = await client.getMailboxLock(folder) try { - const total = client.mailbox?.exists ?? 0 + const mb = client.mailbox + const total = (mb && typeof mb === 'object' && 'exists' in mb) ? mb.exists ?? 0 : 0 if (total === 0) { return { messages: [], total: 0 } } @@ -151,6 +152,7 @@ export async function listMessages( headers: ['content-type'], })) { const env = msg.envelope + if (!env) continue messages.push({ uid: msg.uid, from: env.from?.[0] @@ -184,8 +186,10 @@ export async function getMessage( return withClient(async (client) => { const lock = await client.getMailboxLock(folder) try { - const raw = await client.fetchOne(String(uid), { source: true, flags: true, uid: true }, { uid: true }) - if (!raw?.source) return null + const rawResult = await client.fetchOne(String(uid), { source: true, flags: true, uid: true }, { uid: true }) + if (!rawResult) return null + const raw = rawResult + if (!raw.source) return null const parsed = await simpleParser(raw.source) @@ -203,7 +207,7 @@ export async function getMessage( flags: Array.from(raw.flags || []), html: parsed.html || '', text: parsed.text || '', - attachments: (parsed.attachments || []).map((att) => ({ + attachments: (parsed.attachments || []).map((att: { filename?: string; contentType?: string; size?: number; contentId?: string; contentDisposition?: string }) => ({ filename: att.filename || 'attachment', contentType: att.contentType || 'application/octet-stream', size: att.size || 0, @@ -269,7 +273,7 @@ export async function deleteMessage( // Try to move to Trash first const mailboxes = await client.list() const trash = mailboxes.find( - (mb) => (mb as Record).specialUse === '\\Trash' + (mb) => (mb as unknown as Record).specialUse === '\\Trash' ) if (trash && folder !== trash.path) { @@ -292,7 +296,7 @@ export async function searchMessages( return withClient(async (client) => { const lock = await client.getMailboxLock(folder) try { - const uids = await client.search( + const searchResult = await client.search( { or: [ { subject: query }, @@ -304,6 +308,7 @@ export async function searchMessages( { uid: true } ) + const uids = Array.isArray(searchResult) ? searchResult : [] if (uids.length === 0) return [] // Limit results @@ -317,6 +322,7 @@ export async function searchMessages( flags: true, }, { uid: true })) { const env = msg.envelope + if (!env) continue messages.push({ uid: msg.uid, from: env.from?.[0]