macsync/docs/modules/ireminders.md

3.3 KiB

iReminders (IReminderSync)

Purpose

Sync Reminders.app lists and items with the server, and apply web-initiated edits back via EventKit.

Direction

Bidirectional. Inbound: EventKit -> server. Outbound: icloud.reminder_send_queue -> EKEventStore.save(EKReminder, commit:) / .remove(_, commit:).

OS surface

EventKit (EKEntityType.reminder). Package.swift:84-86 links EventKit. Reader uses EKEventStore.fetchReminders(matching:completion:) (@packages/ireminders/Sources/IReminderSync/Reader.swift:127).

Files

  • Reader.swiftclass ReminderReader (line 66) with requestAuthorization() (line 80), fetchCalendars() (line 110), fetchReminders(since:) (line 124).
  • APIClient.swift:
    • syncReminders(_:) -> POST /client/ireminders/sync (@packages/ireminders/Sources/IReminderSync/APIClient.swift:115)
    • getStats() -> GET /client/ireminders/stats (line 128)
    • getPendingSends() -> GET /client/ireminders/send-queue/pending (line 142)
    • reportSendResult(...) -> POST /client/ireminders/send-queue/:id/result (line 168)
  • Sender.swift — reminder applier wired into a SendQueueClient at @packages/ireminders/Sources/IReminderSync/SyncManager.swift:57.
  • SyncManager.swift — read interval 300s (line 67), send interval 60s (line 57); persistence key "ireminders" (line 66).

Timing

  • Read interval: 300s (SyncManager.swift:67).
  • Outbound poll interval: 60s (SyncManager.swift:57).

Server surface

  • Entity tables: icloud.reminders, icloud.reminder_send_queue (src/server/src/app/server.ts:45-46).
  • Allowed actions: create_reminder, update_reminder, delete_reminder (src/server/src/entities/reminderSendItem/types.ts:16-18).
  • Client routes (src/server/src/surfaces/client/ireminders.ts):
    • POST /client/ireminders/sync (line 32)
    • GET /client/ireminders/stats (line 38)
    • GET /client/ireminders/send-queue/pending (line 42)
    • POST /client/ireminders/send-queue/:id/result (line 60)
  • Web routes (src/server/src/surfaces/my/reminders.ts):
    • GET /my/reminders/stats (line 45)
    • GET /my/reminders/ (line 53)
    • POST /my/reminders/ (line 73)
    • PUT /my/reminders/:id (line 87)
    • DELETE /my/reminders/:id (line 103)
  • Admin enqueue: POST /admin/reminder-send-queue/enqueue (src/server/src/surfaces/admin/reminder-send-queue.ts:16).

Web surface

  • Tab: /reminders (web/src/App.tsx:61).
  • API helpers: web/src/api/reminders.ts.

EventKit snippets

let predicate = store.predicateForReminders(in: nil)
store.fetchReminders(matching: predicate) { reminders in /* ... */ }
// outbound:
try store.save(reminder, commit: true)
try store.remove(reminder, commit: true)

(Source: @packages/ireminders/Sources/IReminderSync/Reader.swift:124-145.)

Known limitations

  • Last-write-wins, same as iCal.
  • Subtasks: EventKit exposes hierarchical reminders via parent/children but the schema flattens; check entities/reminder/ if you need recursion.

Tests (@packages/ireminders/Tests/IReminderSyncTests/)

  • ReaderTests.swift — Reader helpers that don't need EventKit data.
  • SenderTests.swift — applier dispatch (hermetic).

Not covered: actual fetchReminders / save / remove (needs the OS), authorization prompts.