Files
calendar/packages/lib/holidays/GoogleCalendarClient.ts
T
e2119879ae refactor: apply biome formatting to packages/sms, prisma, emails, lib (#27880)
* refactor: apply biome formatting to small packages + packages/lib

Format packages/sms, packages/prisma, packages/platform/libraries,
packages/platform/examples, packages/platform/types, packages/emails,
and packages/lib.

Excludes packages/platform/examples/base/src/pages/[bookingUid].tsx
due to pre-existing lint errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* revert: remove packages/platform formatting changes

Revert biome formatting for packages/platform as requested.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 07:39:01 -03:00

96 lines
2.4 KiB
TypeScript

import dayjs from "@calcom/dayjs";
import { GOOGLE_HOLIDAY_CALENDARS } from "./constants";
interface GoogleCalendarEvent {
id: string;
summary: string;
description?: string;
start: {
date?: string;
dateTime?: string;
};
end: {
date?: string;
dateTime?: string;
};
}
interface GoogleCalendarEventsResponse {
items?: GoogleCalendarEvent[];
error?: {
code: number;
message: string;
};
}
export interface GoogleCalendarHoliday {
id: string;
countryCode: string;
eventId: string;
name: string;
date: Date;
year: number;
}
export class GoogleCalendarClient {
private apiKey: string;
constructor(apiKey?: string) {
const key = apiKey || process.env.GOOGLE_CALENDAR_API_KEY;
if (!key) {
throw new Error("GOOGLE_CALENDAR_API_KEY environment variable is not set");
}
this.apiKey = key;
}
async fetchHolidays(countryCode: string, year: number): Promise<GoogleCalendarHoliday[]> {
const calendarConfig = GOOGLE_HOLIDAY_CALENDARS[countryCode];
if (!calendarConfig) {
return [];
}
const calendarId = encodeURIComponent(calendarConfig.calendarId);
const timeMin = dayjs(`${year}-01-01`).startOf("day").toISOString();
const timeMax = dayjs(`${year}-12-31`).endOf("day").toISOString();
const url = `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events?key=${this.apiKey}&timeMin=${timeMin}&timeMax=${timeMax}&singleEvents=true&orderBy=startTime`;
const response = await fetch(url);
const data: GoogleCalendarEventsResponse = await response.json();
if (data.error) {
console.error(`Google Calendar API error for ${countryCode}:`, data.error);
throw new Error(`Google Calendar API error: ${data.error.message}`);
}
if (!data.items) {
return [];
}
return data.items.map((event) => {
const dateStr = event.start.date || event.start.dateTime?.split("T")[0];
const date = dateStr ? dayjs(dateStr).toDate() : new Date();
return {
id: `${countryCode}_${event.id}`,
countryCode,
eventId: event.id,
name: event.summary,
date,
year,
};
});
}
}
let defaultClient: GoogleCalendarClient | null = null;
export function getGoogleCalendarClient(): GoogleCalendarClient {
if (!defaultClient) {
defaultClient = new GoogleCalendarClient();
}
return defaultClient;
}