@molecule/app-device-calendar
Native · native · App (browser) · v1.0.2 · Apache-2.0
Device/OS calendar access — read & write the user's real iOS/Android calendars (not the in-app calendar UI; that is @molecule/app-calendar)
npm install @molecule/app-device-calendarHow it works
@molecule/app-device-calendar bridges the native core to the native platform layer of the app.
import {
createEvent,
getCalendars,
getEvents,
getPermissionStatus,
hasProvider,
requestPermission,
} from '@molecule/app-device-calendar'
async function addReminderToDeviceCalendar(): Promise<void> {
if (!hasProvider()) return // no provider wired — feature-gate the UI
if ((await getPermissionStatus()) !== 'granted') {
if ((await requestPermission()) !== 'granted') return
}
const writable = (await getCalendars()).find((c) => !c.readOnly)
if (!writable) return
await createEvent({
calendarId: writable.id,
title: 'Dentist',
startDate: '2026-08-01T09:00:00.000Z',
endDate: '2026-08-01T09:30:00.000Z',
allDay: false,
})
}Works with: @molecule/app-bond, @molecule/app-i18n
Reference
Device calendar access interface for molecule.dev.
Framework-agnostic core for reading and writing events in the DEVICE's
calendar store (the user's actual iOS/Android calendars) through a
swappable CalendarProvider: list calendars, query/create/update/delete
events, open the native calendar app, and manage permissions. Also ships
pure helpers (eventsOverlap, getEventDuration, formatEventTimeRange,
parseQuickEvent).
NOT the same package as @molecule/app-calendar — that is the calendar
UI core (month/week/day views rendered inside your app). This package
talks to the operating system's calendar database. Pick by need: rendering
a calendar screen → app-calendar; syncing with the user's real calendars
→ app-device-calendar.
Auto-generated, AI-first package reference for the molecule.dev ecosystem. It is written to be read by coding agents as much as by people, and is generated from this package's source — edit
src/index.tsJSDoc, not this file.
Quick Start
import {
createEvent,
getCalendars,
getEvents,
getPermissionStatus,
hasProvider,
requestPermission,
} from '@molecule/app-device-calendar'
async function addReminderToDeviceCalendar(): Promise<void> {
if (!hasProvider()) return // no provider wired — feature-gate the UI
if ((await getPermissionStatus()) !== 'granted') {
if ((await requestPermission()) !== 'granted') return
}
const writable = (await getCalendars()).find((c) => !c.readOnly)
if (!writable) return
await createEvent({
calendarId: writable.id,
title: 'Dentist',
startDate: '2026-08-01T09:00:00.000Z',
endDate: '2026-08-01T09:30:00.000Z',
allDay: false,
})
}
Type
native
Installation
npm install @molecule/app-device-calendar @molecule/app-bond @molecule/app-i18n
API
Interfaces
Calendar
Device calendar metadata (ID, title, color, read-only flag, account, visibility).
interface Calendar {
/** Calendar ID */
id: string
/** Calendar title/name */
title: string
/** Calendar color */
color?: string
/** Whether calendar is read-only */
readOnly: boolean
/** Calendar type */
type: 'local' | 'subscription' | 'birthday' | 'exchange' | 'google' | 'other'
/** Account name */
accountName?: string
/** Whether calendar is visible */
visible: boolean
}
EventAttendee
A calendar event attendee with email, name, RSVP status, and organizer/optional flags.
interface EventAttendee {
/** Attendee email */
email: string
/** Attendee name */
name?: string
/** Attendance status */
status?: 'pending' | 'accepted' | 'declined' | 'tentative'
/** Whether attendee is organizer */
isOrganizer?: boolean
/** Whether attendee is optional */
isOptional?: boolean
}
EventReminder
Event reminder/alarm
interface EventReminder {
/** Minutes before event to trigger reminder */
minutes: number
/** Reminder method */
method?: 'alert' | 'email' | 'sms'
}
RecurrenceRule
Recurrence rule
interface RecurrenceRule {
/** Recurrence frequency */
frequency: 'daily' | 'weekly' | 'monthly' | 'yearly'
/** Interval between occurrences */
interval?: number
/** End date (ISO string) */
endDate?: string
/** Number of occurrences */
count?: number
/** Days of week (0-6, Sunday-Saturday) */
daysOfWeek?: number[]
/** Days of month (1-31) */
daysOfMonth?: number[]
/** Months (1-12) */
months?: number[]
}
CalendarEvent
Full calendar event with title, dates, location, attendees, reminders, and recurrence rules.
interface CalendarEvent {
/** Event ID */
id: string
/** Calendar ID */
calendarId: string
/** Event title */
title: string
/** Event description */
description?: string
/** Event location */
location?: string
/** Start date/time (ISO string) */
startDate: string
/** End date/time (ISO string) */
endDate: string
/** Whether event is all-day */
allDay: boolean
/** Event timezone */
timezone?: string
/** Event URL */
url?: string
/** Event notes */
notes?: string
/** Attendees */
attendees?: EventAttendee[]
/** Reminders */
reminders?: EventReminder[]
/** Recurrence rule */
recurrence?: RecurrenceRule
/** Event status */
status?: 'confirmed' | 'tentative' | 'cancelled'
/** Event availability */
availability?: 'busy' | 'free' | 'tentative'
/** Organizer info */
organizer?: EventAttendee
}
EventQueryOptions
Event query options
interface EventQueryOptions {
/** Calendar IDs to query (all if not specified) */
calendarIds?: string[]
/** Start date range (ISO string) */
startDate?: string
/** End date range (ISO string) */
endDate?: string
/** Search query */
query?: string
/** Maximum results */
limit?: number
}
CalendarCapabilities
Calendar capabilities
interface CalendarCapabilities {
/** Whether calendar access is supported */
supported: boolean
/** Whether reading is supported */
canRead: boolean
/** Whether writing is supported */
canWrite: boolean
/** Whether reminders are supported */
supportsReminders: boolean
/** Whether recurrence is supported */
supportsRecurrence: boolean
/** Whether attendees are supported */
supportsAttendees: boolean
}
CalendarProvider
Calendar provider interface
interface CalendarProvider {
/**
* Get all calendars available on the device.
* @returns An array of Calendar objects with their metadata.
*/
getCalendars(): Promise<Calendar[]>
/**
* Query calendar events matching the given options.
* @param options - Query filters (calendar IDs, date range, search text, limit).
* @returns An array of matching CalendarEvent objects.
*/
getEvents(options?: EventQueryOptions): Promise<CalendarEvent[]>
/**
* Get a single event by ID
* @param eventId - Event ID
* @param calendarId - Calendar ID
*/
getEventById(eventId: string, calendarId: string): Promise<CalendarEvent | null>
/**
* Create a new event
* @param event - Event data
*/
createEvent(event: EventInput): Promise<CalendarEvent>
/**
* Update an existing event
* @param eventId - Event ID
* @param event - Updated event data
*/
updateEvent(eventId: string, event: Partial<EventInput>): Promise<CalendarEvent>
/**
* Delete an event
* @param eventId - Event ID
* @param calendarId - Calendar ID
*/
deleteEvent(eventId: string, calendarId: string): Promise<void>
/**
* Open native calendar for a date
* @param date - Date to show
*/
openCalendar(date?: Date): Promise<void>
/**
* Open event in native calendar
* @param eventId - Event ID
*/
openEvent(eventId: string): Promise<void>
/**
* Get permission status
*/
getPermissionStatus(): Promise<CalendarPermissionStatus>
/**
* Request permission
*/
requestPermission(): Promise<CalendarPermissionStatus>
/**
* Open system settings for calendar permission
*/
openSettings(): Promise<void>
/**
* Get the platform's calendar capabilities.
* @returns The capabilities indicating which calendar features are supported.
*/
getCapabilities(): Promise<CalendarCapabilities>
}
Types
EventInput
Event input for creation/update
type EventInput = Omit<CalendarEvent, 'id'> & { id?: string }
CalendarPermissionStatus
Permission status
type CalendarPermissionStatus = 'granted' | 'denied' | 'limited' | 'prompt' | 'unsupported'
Functions
setProvider(provider)
Set the device calendar provider.
function setProvider(provider: CalendarProvider): void
provider— CalendarProvider implementation to register.
getProvider()
Get the current device calendar provider.
function getProvider(): CalendarProvider
Returns: The active CalendarProvider instance.
hasProvider()
Check if a calendar provider has been registered.
function hasProvider(): boolean
Returns: Whether a CalendarProvider has been bonded.
getCalendars()
Get all calendars available on the device.
function getCalendars(): Promise<Calendar[]>
Returns: An array of Calendar objects with their metadata.
getEvents(options)
Query calendar events matching the given options.
function getEvents(options?: EventQueryOptions): Promise<CalendarEvent[]>
options— Query filters (calendar IDs, date range, search text, limit).
Returns: An array of matching CalendarEvent objects.
getEventById(eventId, calendarId)
Get a single event by its ID.
function getEventById(eventId: string, calendarId: string): Promise<CalendarEvent | null>
eventId— The event ID to look up.calendarId— The calendar ID containing the event.
Returns: The matching CalendarEvent, or null if not found.
createEvent(event)
Create a new calendar event.
function createEvent(event: EventInput): Promise<CalendarEvent>
event— The event data to create (title, dates, attendees, etc.).
Returns: The created CalendarEvent with its assigned ID.
updateEvent(eventId, event)
Update an existing calendar event.
function updateEvent(eventId: string, event: Partial<EventInput>): Promise<CalendarEvent>
eventId— The ID of the event to update.event— The partial event data to merge with the existing event.
Returns: The updated CalendarEvent.
deleteEvent(eventId, calendarId)
Delete a calendar event.
function deleteEvent(eventId: string, calendarId: string): Promise<void>
eventId— The ID of the event to delete.calendarId— The calendar ID containing the event.
Returns: A promise that resolves when the event is deleted.
openCalendar(date)
Open the native calendar app, optionally showing a specific date.
function openCalendar(date?: Date): Promise<void>
date— The date to navigate to (defaults to today).
Returns: A promise that resolves when the calendar app is opened.
openEvent(eventId)
Open a specific event in the native calendar app.
function openEvent(eventId: string): Promise<void>
eventId— The ID of the event to open.
Returns: A promise that resolves when the event is opened.
getPermissionStatus()
Get the current calendar permission status.
function getPermissionStatus(): Promise<CalendarPermissionStatus>
Returns: The permission status: 'granted', 'denied', 'limited', 'prompt', or 'unsupported'.
requestPermission()
Request calendar permissions from the user.
function requestPermission(): Promise<CalendarPermissionStatus>
Returns: The resulting permission status after the request.
openSettings()
Open the system settings screen for calendar permissions.
function openSettings(): Promise<void>
Returns: A promise that resolves when the settings screen is opened.
getCapabilities()
Get the platform's calendar capabilities.
function getCapabilities(): Promise<CalendarCapabilities>
Returns: The capabilities indicating which calendar features are supported.
eventsOverlap(event1, event2)
Check if two calendar events overlap in time.
function eventsOverlap(event1: CalendarEvent, event2: CalendarEvent): boolean
event1— The first event to compare.event2— The second event to compare.
Returns: Whether the two events have overlapping time ranges.
getEventDuration(event)
Get the duration of a calendar event in minutes.
function getEventDuration(event: CalendarEvent): number
event— The calendar event to measure.
Returns: The event duration in minutes, rounded to the nearest integer.
formatEventTimeRange(event, locale)
Format an event's time range as a human-readable string. Handles all-day events, same-day events, and multi-day events differently.
function formatEventTimeRange(event: CalendarEvent, locale?: string): string
event— The calendar event to format.locale— The locale code for date/time formatting (default: 'en-US').
Returns: A formatted time range string (e.g., "9:00 AM - 10:00 AM" or "Mon, Jan 5").
parseQuickEvent(text, calendarId)
Parse a text string into a quick calendar event. Uses basic keyword matching for time references. Returns null if no title can be extracted.
function parseQuickEvent(text: string, calendarId: string): EventInput | null
text— Natural language event text (e.g., "Meeting tomorrow at 3pm").calendarId— The calendar ID to assign the event to.
Returns: An EventInput for a 1-hour event starting at the next hour, or null if parsing fails.
Injection Notes
Requirements
Peer dependencies:
@molecule/app-bond^1.0.1@molecule/app-i18n^1.0.1
Runtime Dependencies
-
@molecule/app-bond -
@molecule/app-i18n -
Every accessor THROWS until
setProvider()is called — there is no web fallback and no prebuilt provider package ships with molecule; supply aCalendarProviderfrom your native runtime and gate the UI onhasProvider(). Browsers cannot read/write the OS calendar store — on web, integrate a server-side calendar API (@molecule/api-calendar) instead. -
Do not confuse this with
@molecule/app-calendar— they share nothing but a similar name. This package bonds its provider under the distinct'device-calendar'key (the calendar UI core uses'calendar'), so both can be wired in the same app without clobbering each other in the registry. -
Request permission from a user gesture at the point of use; a denied prompt is remembered — recovery is
openSettings(). iOS can grant'limited'(write-only add) access. -
Respect
Calendar.readOnly(subscribed/birthday calendars reject writes) and checkgetCapabilities()before offering attendees or recurrence editing — support differs per platform.