conductor(checkpoint): Checkpoint end of Phase 4: Cleanup & Configuration

This commit is contained in:
2026-02-19 07:12:41 -08:00
parent 780e90b1f0
commit 533c240c07
2 changed files with 36 additions and 9 deletions

View File

@@ -74,12 +74,13 @@ function convertDatesToStrings<T>(obj: T): any {
// Configuration Functions // Configuration Functions
// ============================================================================ // ============================================================================
async function getSources(): Promise<any[]> { async function getSources(): Promise<{ sources: any[], syncWindowDays: number }> {
try { try {
const rawConfig = await config.get("icalendar", { sources: [] }) as any; const rawConfig = await config.get("icalendar", { sources: [] }) as any;
console.log("[iCalendar] Raw config retrieved:", JSON.stringify(rawConfig)); console.log("[iCalendar] Raw config retrieved:", JSON.stringify(rawConfig));
let sources = rawConfig.sources || []; let sources = rawConfig.sources || [];
const syncWindowDays = rawConfig.syncWindowDays || 365;
if (sources && typeof sources === "object" && !Array.isArray(sources)) { if (sources && typeof sources === "object" && !Array.isArray(sources)) {
const sourceArray = []; const sourceArray = [];
@@ -91,10 +92,10 @@ async function getSources(): Promise<any[]> {
sources = sourceArray; sources = sourceArray;
} }
return sources; return { sources, syncWindowDays };
} catch (e) { } catch (e) {
console.error("[iCalendar] Error in getSources:", e); console.error("[iCalendar] Error in getSources:", e);
return []; return { sources: [], syncWindowDays: 365 };
} }
} }
@@ -196,7 +197,7 @@ export function expandRecurrences(icsEvent: any, windowDays = 365): any[] {
} }
} }
async function fetchAndParseCalendar(source: any): Promise<any[]> { async function fetchAndParseCalendar(source: any, windowDays = 365): Promise<any[]> {
console.log(`[iCalendar] Fetching from: ${source.url}`); console.log(`[iCalendar] Fetching from: ${source.url}`);
try { try {
const response = await fetch(source.url); const response = await fetch(source.url);
@@ -231,7 +232,7 @@ async function fetchAndParseCalendar(source: any): Promise<any[]> {
baseEvent.description = `(Warning: Unknown timezone "${rawTz}") ${baseEvent.description || ""}`; baseEvent.description = `(Warning: Unknown timezone "${rawTz}") ${baseEvent.description || ""}`;
} }
const expanded = expandRecurrences(baseEvent); const expanded = expandRecurrences(baseEvent, windowDays);
for (const occurrence of expanded) { for (const occurrence of expanded) {
const uniqueKey = `${occurrence.start}${occurrence.uid || occurrence.summary || ''}`; const uniqueKey = `${occurrence.start}${occurrence.uid || occurrence.summary || ''}`;
occurrence.ref = await sha256Hash(uniqueKey); occurrence.ref = await sha256Hash(uniqueKey);
@@ -247,13 +248,13 @@ async function fetchAndParseCalendar(source: any): Promise<any[]> {
export async function syncCalendars() { export async function syncCalendars() {
try { try {
const sources = await getSources(); const { sources, syncWindowDays } = await getSources();
if (sources.length === 0) return; if (sources.length === 0) return;
await editor.flashNotification("Syncing calendars...", "info"); await editor.flashNotification("Syncing calendars...", "info");
const allEvents: any[] = []; const allEvents: any[] = [];
for (const source of sources) { for (const source of sources) {
const events = await fetchAndParseCalendar(source); const events = await fetchAndParseCalendar(source, syncWindowDays);
allEvents.push(...events); allEvents.push(...events);
} }
await index.indexObjects("$icalendar", allEvents); await index.indexObjects("$icalendar", allEvents);

View File

@@ -76,6 +76,32 @@ Deno.test("expandRecurrences - EXDATE exclusion", () => {
Deno.test("fetchAndParseCalendar - filter cancelled events", async () => { Deno.test("fetchAndParseCalendar - filter cancelled events", async () => {
// This requires mocking fetch or testing the inner loop logic. // This requires mocking fetch or testing the inner loop logic.
// For now, let's just test that we skip them if we had a list of events. });
// Since fetchAndParseCalendar is async and uses syscalls, we'll verify the logic in the code.
Deno.test("resolveEventStart - ignore tzShift", async () => {
const icsEvent = {
summary: "Ignore tzShift",
start: {
date: "2025-01-15T12:00:00.000",
local: {
date: "2025-01-15T07:00:00.000",
timezone: "Eastern Standard Time"
}
}
};
const result = await resolveEventStart(icsEvent);
assertEquals(result?.toISOString(), "2025-01-15T12:00:00.000Z");
});
Deno.test("expandRecurrences - custom windowDays", () => {
const icsEvent = {
summary: "Daily Meeting",
start: "2025-01-01T10:00:00",
rrule: "FREQ=DAILY"
};
// 7 days window (Jan 1 to Jan 8) should give 8 occurrences if inclusive
const results = expandRecurrences(icsEvent, 7);
assertEquals(results.length, 8);
}); });