/** * calendar-connector.ts, the high-level connector the agent drives. It ties the * provider profiles, the OAuth flows, the secret-backed token store, and the two API * clients into one surface: connect (auth-code or device-code), disconnect, list * accounts + their honest state, list calendars, list events (normalized + source- * labeled) across a window, and create an event routed to an explicitly chosen * provider. The network and (for the loopback flow) the redirect listener are * injected, so the whole thing runs against fakes with no real network or port. */ import { type Sleep } from './oauth-flow.js'; import { type CalendarConfigReader, type CalendarSecretReader } from './oauth-client-config.js'; import { type CalendarUntrustedIngestRecorder } from './untrusted-events.js'; import type { AuthCodeFlowStart, CalendarProviderId, Clock, ConnectedAccount, ConnectionState, DeviceCodeFlowStart, HttpFetch, LoopbackListenerFactory, LoopbackWaiter, MergedCalendarEvent, NewCalendarEvent, OAuthClientOverrides, ProviderCalendar, ResolvedClientConfig, SecretStoreSlice } from './oauth-types.js'; export interface CalendarConnectorOptions { readonly secrets: SecretStoreSlice; readonly fetchImpl: HttpFetch; readonly clock?: Clock; /** Required only for the auth-code (loopback) flow; device-code needs no listener. */ readonly listenerFactory?: LoopbackListenerFactory; /** Injected delay for device-code polling; defaults to a real timer. */ readonly sleep?: Sleep; readonly refreshLeewayMs?: number; /** * Records that a turn read untrusted event content. * * Called from `listEvents`, a read someone asked for, and from nowhere * else. An event the provider says the owner organized is not recorded; an * invitation somebody else sent is. See untrusted-events.ts. */ readonly recordUntrustedIngest?: CalendarUntrustedIngestRecorder; } /** A time window for event listing, as ISO strings. */ export interface EventWindow { readonly timeMin: string; readonly timeMax: string; } export declare class CalendarConnector { private readonly secrets; private readonly fetchImpl; private readonly clock; private readonly listenerFactory?; private readonly sleep; private readonly store; private readonly recordUntrustedIngest?; constructor(options: CalendarConnectorOptions); /** Resolve the client config for a provider (profile + the operator's credentials). */ resolveConfig(provider: CalendarProviderId, overrides?: OAuthClientOverrides): ResolvedClientConfig; /** * Resolve the client config from the operator's SETTINGS, the normal path. * * `resolveConfig` takes credentials a caller already holds; this reads them * from `calendar..clientId` and the client-secret reference beside * it, which is where registering your own OAuth app puts them. A config with * nothing set resolves to `isConfigured: false`, so a status view can render * "not set up" and a connect attempt refuses naming the key, neither of them * has to know the key string itself. */ resolveConfigFromSettings(provider: CalendarProviderId, sources: { readonly config: CalendarConfigReader; readonly secretGet?: CalendarSecretReader | undefined; readonly extra?: Omit | undefined; }): Promise; listAccounts(): Promise; connectionState(provider: CalendarProviderId): Promise; /** Begin the loopback auth-code flow; returns the URL to open and the waiter. */ beginConnectAuthCode(config: ResolvedClientConfig): Promise<{ readonly start: AuthCodeFlowStart; readonly waiter: LoopbackWaiter; }>; /** Complete the auth-code flow after the redirect delivered a code; saves tokens. */ completeConnectAuthCode(config: ResolvedClientConfig, input: { readonly code: string; readonly verifier: string; readonly redirectUri: string; }): Promise; /** Begin the device-code flow; returns the user code + verification URL to show. */ beginConnectDeviceCode(config: ResolvedClientConfig): Promise; /** Poll until the device code is approved, then save tokens. */ completeConnectDeviceCode(config: ResolvedClientConfig, start: DeviceCodeFlowStart): Promise; disconnect(provider: CalendarProviderId, overrides?: OAuthClientOverrides): Promise<{ readonly revokedRemotely: boolean; }>; /** List the provider's calendars (refreshing the token first when due). */ listCalendars(config: ResolvedClientConfig): Promise; /** * List events across all of the provider's calendars in a window, normalized into * the merged model, source-labeled, and sorted chronologically (through the ONE * documented cross-zone comparator, `compareMergedCalendarEventsByStart`, see * merged-calendar-model.ts for why a raw string/localeCompare sort of `start.value` * is wrong once utc and tzid/floating events are mixed). Callers merge this with * A9's ICS/local events into the unified /calendar view. */ listEvents(config: ResolvedClientConfig, window: EventWindow): Promise; createEvent(config: ResolvedClientConfig, calendarId: string, calendarLabel: string, event: NewCalendarEvent): Promise; /** Save tokens + a best-effort enriched account label, and return the account. */ private persistConnection; /** * Best-effort account label: the primary calendar id is the account email for * Google, and the primary calendar's name is a reasonable Outlook label. A failure * here must NOT fail the connection (the token is already valid), so it falls back * to the provider display name. */ private deriveLabel; } //# sourceMappingURL=calendar-connector.d.ts.map