unical library

unical — one resilient API over device calendars and CalDAV for events and tasks with progress.

The core is pure Dart. Bring a CalendarBackend (see unical_caldav and unical_flutter), wrap it in a SyncEngine, and drive it through the fail-safe UnicalClient. The engine picks the best MetadataStrategy the backend can honor — native VTODO, invisible X- properties, an opt-in description block, or drift-only — so task metadata never gets lost even on servers that cannot store tasks.

Classes

CalendarBackend
A pluggable calendar backend. Implementations wrap caldav, device_calendar_plus, or an in-memory fake. All methods may throw; the fail-safe wrapping lives in UnicalClient, not here.
Capabilities
What a concrete backend can actually preserve. Drives the choice of metadata strategy (see MetadataStrategy.select).
DescriptionCodec
Last-resort, user-visible smuggling channel: a delimited block appended to the event DESCRIPTION. Only this survives servers that strip everything else (Google via CalDAV, device calendars). It is validated to survive iCalendar 75-octet line folding, CRLF/LF changes, user edits of the human text and corrupted payloads (which degrade to null without losing text).
Ical
Minimal iCalendar (RFC 5545) text helpers shared by the codecs and by backend adapters that manipulate raw .ics payloads.
InMemoryBackend
An in-memory CalendarBackend that faithfully simulates a real server's lossiness according to its Capabilities: it strips X- properties when preservesXProps is false, drops categories when supportsCategories is false, and rejects task operations when supportsVtodo is false. Ideal for tests and as the canonical reference implementation.
InMemoryMappingStore
A simple in-memory MappingStore.
Mapping
A single caller-id → backend-ref mapping, the anchor that lets a sync re-identify its own objects and avoid duplicates.
MappingStore
Persistence seam for Mappings. Implement over Drift in an app; an in-memory implementation ships for tests and ephemeral use.
Outcome<T>
A fail-safe result: either a value or an error, never both. Mirrors the "never throw across the boundary" philosophy of the app's other service wrappers so calendar hiccups can never crash the caller.
ParsedDescription
Result of splitting an event description into its human part and (maybe) the embedded task metadata.
RemoteEvent
An event as returned by a backend: the domain event plus the transport details needed to reconcile it — the backend ref (id or href), any custom X- properties preserved by the server, and the change etag.
RemoteTask
A native VTODO task as returned by a task-capable backend.
SyncEngine
Orchestrates pushing/pulling tasks and events through a CalendarBackend, choosing the best MetadataStrategy the backend can honor and keeping the MappingStore in sync. Never mutates the caller's store — it returns reconstructed objects and the caller decides what to persist.
TaskMeta
The task-only metadata that a plain VEVENT cannot represent natively and that must therefore be smuggled (via X- properties, or as a last resort a description block) when a task is projected onto an event.
UnicalClient
Fail-safe facade over SyncEngine. Every method swallows exceptions and enforces a timeout, returning an Outcome instead of throwing.
UnicalEvent
A calendar event — a block of time (VEVENT). In Stabilitas terms, the period in which the labor is done.
UnicalTask
A task with a completion percentage — the "minor/minima" of the caller's domain. Maps to an iCalendar VTODO where the backend supports it, and to a projected VEVENT (plus smuggled metadata) where it does not.
XPropCodec
Encodes TaskMeta as invisible X-STABILITAS-* iCalendar properties and decodes them back. This is the preferred smuggling channel: the properties never show up in a calendar client's UI. It only works on servers that preserve custom X- properties on round-trip (generic CalDAV) — Google and device calendars strip them, which is why MetadataStrategy gates its use.

Enums

MetadataStrategy
How a task's extra metadata (percent, tags, identity) is carried on the calendar side. Ordered best → worst; select walks the ladder.
TaskStatus
Lifecycle status of a task, mirroring the iCalendar STATUS values that a VTODO accepts (RFC 5545 §3.8.1.11).
Winner
Which side wins when the same object changed locally and remotely.