mirror of
https://github.com/kennethnym/aris.git
synced 2026-03-21 17:41:18 +00:00
Compare commits
3 Commits
6c4982ae85
...
feat/apple
| Author | SHA1 | Date | |
|---|---|---|---|
| 13c411c842 | |||
| e8ba49d7bb | |||
| 3010eb8990 |
@@ -48,12 +48,13 @@ class MockCredentialProvider implements CalendarCredentialProvider {
|
|||||||
|
|
||||||
class MockDAVClient implements CalendarDAVClient {
|
class MockDAVClient implements CalendarDAVClient {
|
||||||
credentials: Record<string, unknown> = {}
|
credentials: Record<string, unknown> = {}
|
||||||
|
fetchCalendarsCallCount = 0
|
||||||
private calendars: CalendarDAVCalendar[]
|
private calendars: CalendarDAVCalendar[]
|
||||||
private objectsByCalendarUrl: Map<string, CalendarDAVObject[]>
|
private objectsByCalendarUrl: Record<string, CalendarDAVObject[]>
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
calendars: CalendarDAVCalendar[],
|
calendars: CalendarDAVCalendar[],
|
||||||
objectsByCalendarUrl: Map<string, CalendarDAVObject[]>,
|
objectsByCalendarUrl: Record<string, CalendarDAVObject[]>,
|
||||||
) {
|
) {
|
||||||
this.calendars = calendars
|
this.calendars = calendars
|
||||||
this.objectsByCalendarUrl = objectsByCalendarUrl
|
this.objectsByCalendarUrl = objectsByCalendarUrl
|
||||||
@@ -62,6 +63,7 @@ class MockDAVClient implements CalendarDAVClient {
|
|||||||
async login(): Promise<void> {}
|
async login(): Promise<void> {}
|
||||||
|
|
||||||
async fetchCalendars(): Promise<CalendarDAVCalendar[]> {
|
async fetchCalendars(): Promise<CalendarDAVCalendar[]> {
|
||||||
|
this.fetchCalendarsCallCount++
|
||||||
return this.calendars
|
return this.calendars
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,7 +71,7 @@ class MockDAVClient implements CalendarDAVClient {
|
|||||||
calendar: CalendarDAVCalendar
|
calendar: CalendarDAVCalendar
|
||||||
timeRange: { start: string; end: string }
|
timeRange: { start: string; end: string }
|
||||||
}): Promise<CalendarDAVObject[]> {
|
}): Promise<CalendarDAVObject[]> {
|
||||||
return this.objectsByCalendarUrl.get(params.calendar.url) ?? []
|
return this.objectsByCalendarUrl[params.calendar.url] ?? []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +88,7 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("returns empty array when no calendars exist", async () => {
|
test("returns empty array when no calendars exist", async () => {
|
||||||
const client = new MockDAVClient([], new Map())
|
const client = new MockDAVClient([], {})
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
})
|
})
|
||||||
@@ -95,9 +97,9 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("returns feed items from a single calendar", async () => {
|
test("returns feed items from a single calendar", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -116,13 +118,12 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("returns feed items from multiple calendars", async () => {
|
test("returns feed items from multiple calendars", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
[
|
"/cal/personal": [
|
||||||
"/cal/personal",
|
{ url: "/cal/personal/event2.ics", data: loadFixture("all-day-event.ics") },
|
||||||
[{ url: "/cal/personal/event2.ics", data: loadFixture("all-day-event.ics") }],
|
|
||||||
],
|
],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient(
|
const client = new MockDAVClient(
|
||||||
[
|
[
|
||||||
{ url: "/cal/work", displayName: "Work" },
|
{ url: "/cal/work", displayName: "Work" },
|
||||||
@@ -150,16 +151,13 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("skips objects with non-string data", async () => {
|
test("skips objects with non-string data", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
[
|
"/cal/work": [
|
||||||
"/cal/work",
|
|
||||||
[
|
|
||||||
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
||||||
{ url: "/cal/work/bad.ics", data: 12345 },
|
{ url: "/cal/work/bad.ics", data: 12345 },
|
||||||
{ url: "/cal/work/empty.ics" },
|
{ url: "/cal/work/empty.ics" },
|
||||||
],
|
],
|
||||||
],
|
}
|
||||||
])
|
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -171,9 +169,9 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("uses context time as feed item timestamp", async () => {
|
test("uses context time as feed item timestamp", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -185,15 +183,12 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("assigns priority based on event proximity", async () => {
|
test("assigns priority based on event proximity", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
[
|
"/cal/work": [
|
||||||
"/cal/work",
|
|
||||||
[
|
|
||||||
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
||||||
{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") },
|
{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") },
|
||||||
],
|
],
|
||||||
],
|
}
|
||||||
])
|
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -210,9 +205,9 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("handles calendar with non-string displayName", async () => {
|
test("handles calendar with non-string displayName", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/weird", [{ url: "/cal/weird/event1.ics", data: loadFixture("minimal-event.ics") }]],
|
"/cal/weird": [{ url: "/cal/weird/event1.ics", data: loadFixture("minimal-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient(
|
const client = new MockDAVClient(
|
||||||
[{ url: "/cal/weird", displayName: { _cdata: "Weird Calendar" } }],
|
[{ url: "/cal/weird", displayName: { _cdata: "Weird Calendar" } }],
|
||||||
objects,
|
objects,
|
||||||
@@ -226,9 +221,9 @@ describe("CalendarSource", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("handles recurring events with exceptions", async () => {
|
test("handles recurring events with exceptions", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/recurring.ics", data: loadFixture("recurring-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/recurring.ics", data: loadFixture("recurring-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -248,6 +243,40 @@ describe("CalendarSource", () => {
|
|||||||
expect(exception!.data.recurrenceId).not.toBeNull()
|
expect(exception!.data.recurrenceId).not.toBeNull()
|
||||||
expect(exception!.id).toContain("-")
|
expect(exception!.id).toContain("-")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("caches events within the same refresh cycle", async () => {
|
||||||
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
|
}
|
||||||
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
|
davClient: client,
|
||||||
|
})
|
||||||
|
|
||||||
|
const context = createContext(new Date("2026-01-15T12:00:00Z"))
|
||||||
|
|
||||||
|
await source.fetchContext(context)
|
||||||
|
await source.fetchItems(context)
|
||||||
|
|
||||||
|
// Same context.time reference — fetchEvents should only hit the client once
|
||||||
|
expect(client.fetchCalendarsCallCount).toBe(1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("refetches events for a different context time", async () => {
|
||||||
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
|
}
|
||||||
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
|
davClient: client,
|
||||||
|
})
|
||||||
|
|
||||||
|
await source.fetchItems(createContext(new Date("2026-01-15T12:00:00Z")))
|
||||||
|
await source.fetchItems(createContext(new Date("2026-01-15T13:00:00Z")))
|
||||||
|
|
||||||
|
// Different context.time references — should fetch twice
|
||||||
|
expect(client.fetchCalendarsCallCount).toBe(2)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("CalendarSource.fetchContext", () => {
|
describe("CalendarSource.fetchContext", () => {
|
||||||
@@ -264,9 +293,9 @@ describe("CalendarSource.fetchContext", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("identifies in-progress events", async () => {
|
test("identifies in-progress events", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -281,9 +310,9 @@ describe("CalendarSource.fetchContext", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("identifies next upcoming event", async () => {
|
test("identifies next upcoming event", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -299,9 +328,9 @@ describe("CalendarSource.fetchContext", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("excludes all-day events from inProgress and nextEvent", async () => {
|
test("excludes all-day events from inProgress and nextEvent", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
["/cal/work", [{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") }]],
|
"/cal/work": [{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") }],
|
||||||
])
|
}
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
@@ -317,15 +346,12 @@ describe("CalendarSource.fetchContext", () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test("counts all events including all-day in todayEventCount", async () => {
|
test("counts all events including all-day in todayEventCount", async () => {
|
||||||
const objects = new Map<string, CalendarDAVObject[]>([
|
const objects: Record<string, CalendarDAVObject[]> = {
|
||||||
[
|
"/cal/work": [
|
||||||
"/cal/work",
|
|
||||||
[
|
|
||||||
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
{ url: "/cal/work/event1.ics", data: loadFixture("single-event.ics") },
|
||||||
{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") },
|
{ url: "/cal/work/allday.ics", data: loadFixture("all-day-event.ics") },
|
||||||
],
|
],
|
||||||
],
|
}
|
||||||
])
|
|
||||||
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
const client = new MockDAVClient([{ url: "/cal/work", displayName: "Work" }], objects)
|
||||||
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
const source = new CalendarSource(new MockCredentialProvider(), "user-1", {
|
||||||
davClient: client,
|
davClient: client,
|
||||||
|
|||||||
@@ -8,9 +8,15 @@ import type {
|
|||||||
CalendarDAVClient,
|
CalendarDAVClient,
|
||||||
CalendarEventData,
|
CalendarEventData,
|
||||||
CalendarFeedItem,
|
CalendarFeedItem,
|
||||||
CalendarSourceOptions,
|
|
||||||
} from "./types.ts"
|
} from "./types.ts"
|
||||||
|
|
||||||
|
export interface CalendarSourceOptions {
|
||||||
|
/** Number of additional days beyond today to fetch. Default: 0 (today only). */
|
||||||
|
lookAheadDays?: number
|
||||||
|
/** Optional DAVClient instance for testing. Uses tsdav DAVClient by default. */
|
||||||
|
davClient?: CalendarDAVClient
|
||||||
|
}
|
||||||
|
|
||||||
import { CalendarKey, type CalendarContext } from "./calendar-context.ts"
|
import { CalendarKey, type CalendarContext } from "./calendar-context.ts"
|
||||||
import { parseICalEvents } from "./ical-parser.ts"
|
import { parseICalEvents } from "./ical-parser.ts"
|
||||||
|
|
||||||
@@ -39,6 +45,7 @@ export class CalendarSource implements FeedSource<CalendarFeedItem> {
|
|||||||
private readonly injectedClient: CalendarDAVClient | null
|
private readonly injectedClient: CalendarDAVClient | null
|
||||||
private davClient: CalendarDAVClient | null = null
|
private davClient: CalendarDAVClient | null = null
|
||||||
private lastAccessToken: string | null = null
|
private lastAccessToken: string | null = null
|
||||||
|
private cachedEvents: { time: Date; events: CalendarEventData[] } | null = null
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
credentialProvider: CalendarCredentialProvider,
|
credentialProvider: CalendarCredentialProvider,
|
||||||
@@ -88,6 +95,10 @@ export class CalendarSource implements FeedSource<CalendarFeedItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async fetchEvents(context: Context): Promise<CalendarEventData[]> {
|
private async fetchEvents(context: Context): Promise<CalendarEventData[]> {
|
||||||
|
if (this.cachedEvents && this.cachedEvents.time === context.time) {
|
||||||
|
return this.cachedEvents.events
|
||||||
|
}
|
||||||
|
|
||||||
const credentials = await this.credentialProvider.fetchCredentials(this.userId)
|
const credentials = await this.credentialProvider.fetchCredentials(this.userId)
|
||||||
if (!credentials) {
|
if (!credentials) {
|
||||||
return []
|
return []
|
||||||
@@ -128,6 +139,7 @@ export class CalendarSource implements FeedSource<CalendarFeedItem> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.cachedEvents = { time: context.time, events: allEvents }
|
||||||
return allEvents
|
return allEvents
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -52,12 +52,17 @@ function parseVEvent(
|
|||||||
|
|
||||||
function parseStatus(raw: string | null): CalendarEventStatus | null {
|
function parseStatus(raw: string | null): CalendarEventStatus | null {
|
||||||
if (!raw) return null
|
if (!raw) return null
|
||||||
const lower = raw.toLowerCase()
|
switch (raw.toLowerCase()) {
|
||||||
if (lower === "confirmed") return CalendarEventStatus.Confirmed
|
case "confirmed":
|
||||||
if (lower === "tentative") return CalendarEventStatus.Tentative
|
return CalendarEventStatus.Confirmed
|
||||||
if (lower === "cancelled") return CalendarEventStatus.Cancelled
|
case "tentative":
|
||||||
|
return CalendarEventStatus.Tentative
|
||||||
|
case "cancelled":
|
||||||
|
return CalendarEventStatus.Cancelled
|
||||||
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseOrganizer(
|
function parseOrganizer(
|
||||||
value: string | null,
|
value: string | null,
|
||||||
@@ -97,22 +102,33 @@ function parseAttendees(properties: unknown[]): CalendarAttendee[] {
|
|||||||
|
|
||||||
function parseAttendeeRole(raw: string | null): AttendeeRole | null {
|
function parseAttendeeRole(raw: string | null): AttendeeRole | null {
|
||||||
if (!raw) return null
|
if (!raw) return null
|
||||||
const upper = raw.toUpperCase()
|
switch (raw.toUpperCase()) {
|
||||||
if (upper === "CHAIR") return AttendeeRole.Chair
|
case "CHAIR":
|
||||||
if (upper === "REQ-PARTICIPANT") return AttendeeRole.Required
|
return AttendeeRole.Chair
|
||||||
if (upper === "OPT-PARTICIPANT") return AttendeeRole.Optional
|
case "REQ-PARTICIPANT":
|
||||||
|
return AttendeeRole.Required
|
||||||
|
case "OPT-PARTICIPANT":
|
||||||
|
return AttendeeRole.Optional
|
||||||
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseAttendeeStatus(raw: string | null): AttendeeStatus | null {
|
function parseAttendeeStatus(raw: string | null): AttendeeStatus | null {
|
||||||
if (!raw) return null
|
if (!raw) return null
|
||||||
const upper = raw.toUpperCase()
|
switch (raw.toUpperCase()) {
|
||||||
if (upper === "ACCEPTED") return AttendeeStatus.Accepted
|
case "ACCEPTED":
|
||||||
if (upper === "DECLINED") return AttendeeStatus.Declined
|
return AttendeeStatus.Accepted
|
||||||
if (upper === "TENTATIVE") return AttendeeStatus.Tentative
|
case "DECLINED":
|
||||||
if (upper === "NEEDS-ACTION") return AttendeeStatus.NeedsAction
|
return AttendeeStatus.Declined
|
||||||
|
case "TENTATIVE":
|
||||||
|
return AttendeeStatus.Tentative
|
||||||
|
case "NEEDS-ACTION":
|
||||||
|
return AttendeeStatus.NeedsAction
|
||||||
|
default:
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseAlarms(vevent: InstanceType<typeof ICAL.Component>): CalendarAlarm[] {
|
function parseAlarms(vevent: InstanceType<typeof ICAL.Component>): CalendarAlarm[] {
|
||||||
const valarms = vevent.getAllSubcomponents("valarm")
|
const valarms = vevent.getAllSubcomponents("valarm")
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export { CalendarKey, type CalendarContext } from "./calendar-context.ts"
|
export { CalendarKey, type CalendarContext } from "./calendar-context.ts"
|
||||||
export { CalendarSource } from "./calendar-source.ts"
|
export { CalendarSource, type CalendarSourceOptions } from "./calendar-source.ts"
|
||||||
export {
|
export {
|
||||||
CalendarEventStatus,
|
CalendarEventStatus,
|
||||||
AttendeeRole,
|
AttendeeRole,
|
||||||
@@ -13,5 +13,4 @@ export {
|
|||||||
type CalendarAlarm,
|
type CalendarAlarm,
|
||||||
type CalendarEventData,
|
type CalendarEventData,
|
||||||
type CalendarFeedItem,
|
type CalendarFeedItem,
|
||||||
type CalendarSourceOptions,
|
|
||||||
} from "./types.ts"
|
} from "./types.ts"
|
||||||
|
|||||||
@@ -99,12 +99,3 @@ export interface CalendarDAVClient {
|
|||||||
}): Promise<CalendarDAVObject[]>
|
}): Promise<CalendarDAVObject[]>
|
||||||
credentials: Record<string, unknown>
|
credentials: Record<string, unknown>
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- Source options --
|
|
||||||
|
|
||||||
export interface CalendarSourceOptions {
|
|
||||||
/** Number of additional days beyond today to fetch. Default: 0 (today only). */
|
|
||||||
lookAheadDays?: number
|
|
||||||
/** Optional DAVClient instance for testing. Uses tsdav DAVClient by default. */
|
|
||||||
davClient?: CalendarDAVClient
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user