Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support for typescript types? #96

Open
riccardogiorato opened this issue Aug 8, 2022 · 6 comments
Open

support for typescript types? #96

riccardogiorato opened this issue Aug 8, 2022 · 6 comments

Comments

@riccardogiorato
Copy link

riccardogiorato commented Aug 8, 2022

Are you planning to add support for typescript types @victor-cronofy ?

@victor-cronofy
Copy link
Contributor

Thanks for your question.

Typescript support isn't in our plan at the moment. There was a discussion about it but unfortunately it didn't fit in the development roadmap. The effort to support Typescript is not trivial. Hope you understand.

Let us know if there is anything blocking you from using Cronofy API.
Thank you

@riccardogiorato
Copy link
Author

Hey @victor-cronofy we are still considering if we are going to use Cronofy or a competitor like https://www.nylas.com/

They already provide Typescript support to make the development faster and easier, are you planning to support Typescript in the next future (next month)?

@gshutler
Copy link
Member

I'm afraid we're not in a position to provide Typescript types in the near future.

@MOIN-AKHTAR
Copy link

MOIN-AKHTAR commented Jun 1, 2023

It would be great if we can get typecript definition files because while using this sdk i am not able to get suggestion not even for methods which is inside this sdk for that i have to go to implementation files of this sdk and than look there what functions are available and on the other hand for each method i am also not able to find what params or body look like which is kind of very cumbersome to work.

@nabilfreeman
Copy link

Hey all, I've started implementing Cronofy in a new TypeScript project today. I can't promise anything on the level of DefinitelyTyped, but I will share any of the types I write here as a jumping off point for basic use cases.

@nabilfreeman
Copy link

nabilfreeman commented Mar 28, 2024

As promised... I've typed setup, authentication, listing calendars and CRUD events, which is our use case and hopefully many others.

As you can see by all the TODO types, there is a huge number of other methods which I haven't typed.

Earlier today I thought perhaps releasing a community types module was feasible but I think it will take over a week of work to fully type this (despite the documentation being really, really good) and obviously keeping it in sync with new service providers, alpha features etc. has significant ongoing maintenance needs.

But maybe this will help a few people go from zero to one!

I'll edit this comment if/when I update our types file.

// cronofy.d.ts
declare module 'cronofy' {
	export default class Cronofy {
		constructor(config: FactoryOptions);

		requestAccessToken: (options: RequestAccessTokenOptions) => Promise<RequestAccessTokenResponse>;
		refreshAccessToken: () => Promise<RefreshAccessTokenResponse>;
		listCalendars: () => Promise<ListCalendarsResponse>;
		readEvents: (options: ReadEventsOptions) => Promise<ReadEventsResponse>;
		deleteEvent: (options: DeleteEventOptions) => Promise<DeleteEventResponse>;
		createEvent: (options: CreateEventOptions) => Promise<CreateEventResponse>;

		// TODO: Properly type the remaining Cronofy client methods below.
		accountInformation: (TODOInput: TODOInput) => Promise<TODOResponse>;
		addToCalendar: (TODOInput: TODOInput) => Promise<TODOResponse>;
		realTimeScheduling: (TODOInput: TODOInput) => Promise<TODOResponse>;
		realTimeSequencing: (TODOInput: TODOInput) => Promise<TODOResponse>;
		authorizeWithServiceAccount: (TODOInput: TODOInput) => Promise<TODOResponse>;
		availability: (TODOInput: TODOInput) => Promise<TODOResponse>;
		sequencedAvailability: (TODOInput: TODOInput) => Promise<TODOResponse>;
		upsertAvailablePeriod: (TODOInput: TODOInput) => Promise<TODOResponse>;
		listAvailablePeriods: (TODOInput: TODOInput) => Promise<TODOResponse>;
		deleteAvailablePeriods: (TODOInput: TODOInput) => Promise<TODOResponse>;
		listAvailabilityRules: (TODOInput: TODOInput) => Promise<TODOResponse>;
		upsertAvailabilityRule: (TODOInput: TODOInput) => Promise<TODOResponse>;
		readAvailabilityRule: (TODOInput: TODOInput) => Promise<TODOResponse>;
		deleteAvailabilityRule: (TODOInput: TODOInput) => Promise<TODOResponse>;
		createNotificationChannel: (TODOInput: TODOInput) => Promise<TODOResponse>;
		bulkDeleteEvents: (TODOInput: TODOInput) => Promise<TODOResponse>;
		updateExternalEvent: (TODOInput: TODOInput) => Promise<TODOResponse>;
		deleteExternalEvent: (TODOInput: TODOInput) => Promise<TODOResponse>;
		deleteNotificationChannel: (TODOInput: TODOInput) => Promise<TODOResponse>;
		elevatedPermissions: (TODOInput: TODOInput) => Promise<TODOResponse>;
		freeBusy: (TODOInput: TODOInput) => Promise<TODOResponse>;
		createCalendar: (TODOInput: TODOInput) => Promise<TODOResponse>;
		listNotificationChannels: (TODOInput: TODOInput) => Promise<TODOResponse>;
		profileInformation: (TODOInput: TODOInput) => Promise<TODOResponse>;
		applicationCalendar: (TODOInput: TODOInput) => Promise<TODOResponse>;
		revokeProfileAuthorization: (TODOInput: TODOInput) => Promise<TODOResponse>;
		hmacValid: (TODOInput: TODOInput) => Promise<TODOResponse>;
		revokeAuthorization: (TODOInput: TODOInput) => Promise<TODOResponse>;
		getSmartInvite: (TODOInput: TODOInput) => Promise<TODOResponse>;
		createSmartInvite: (TODOInput: TODOInput) => Promise<TODOResponse>;
		cancelSmartInvite: (TODOInput: TODOInput) => Promise<TODOResponse>;
		userInfo: (TODOInput: TODOInput) => Promise<TODOResponse>;
		requestElementToken: (TODOInput: TODOInput) => Promise<TODOResponse>;
		listAccessibleCalendars: (TODOInput: TODOInput) => Promise<TODOResponse>;
		delegatedAuthorizations: (TODOInput: TODOInput) => Promise<TODOResponse>;
		batch: (TODOInput: TODOInput) => Promise<TODOResponse>;
		conferencingServiceAuthorizations: (TODOInput: TODOInput) => Promise<TODOResponse>;
		createBookableEvent: (TODOInput: TODOInput) => Promise<TODOResponse>;
		readBookableEvents: (TODOInput: TODOInput) => Promise<TODOResponse>;
		upsertRegistrationBookableEvent: (TODOInput: TODOInput) => Promise<TODOResponse>;
		deleteRegistrationBookableEvent: (TODOInput: TODOInput) => Promise<TODOResponse>;
	}

	// Inputs
	export type TODOInput = any; // TODO: Define the remaining input types for the Cronofy client methods, and then delete this type.
	export type FactoryOptions = {
		data_center: DataCenter;
		client_id: string;
		client_secret: string;
		access_token: string;
		refresh_token: string;
	};
	export type RequestAccessTokenOptions = {
		client_id: string;
		client_secret: string;
		grant_type: 'authorization_code';
		code: string;
		redirect_uri: string;
	};
	export type ReadEventsOptions = {
		from?: string;
		to?: string;
		tzid: Timezone;
		include_deleted?: boolean;
		include_moved?: boolean;
		last_modified?: string;
		include_managed?: boolean;
		only_managed?: boolean;
		calendar_ids?: string[];
		localized_times?: boolean;
		include_geo?: boolean;
		include_userinfo?: boolean;

		// For pagination
		next_page?: string;
	};
	export type DeleteEventOptions = {
		calendar_id: string;
		event_id: string;
		include_userinfo?: boolean;
	};
	export type CreateEventOptions = {
		calendar_id: string;
		event_id: string;
		summary: string;
		description?: string;
		start: string | EventTimeInZone;
		end: string | EventTimeInZone;
		tzid?: string;
		location?: {
			description?: string;
			lat?: string;
			long?: string;
		};
		url?: string;
		transparency?: 'opaque' | 'transparent';
		extended_transparency?: 'opaque' | 'transparent' | 'working_elsewhere' | 'tentative' | 'out_of_office';
		color?: string;
		reminders?: { minutes: number }[];
		reminders_create_only?: boolean;
		attendees?: {
			invite?: Attendee[];
			remove?: Attendee[];
		};
		event_private?: boolean;
		locale?: string;
		include_userinfo?: boolean;
		tags?: Tags;
		conferencing?: ConferencingInformation;
		subscriptions?: Subscription[];
		recurrence?: {
			rules: RecurrenceRule[];
			exceptions?: {
				add: { date: string }[]; // Array of dates to be excluded from the recurrence pattern
			};
		};
	};

	// Outputs
	export type TODOResponse = any; // TODO: Define the remaining response types for the Cronofy client methods, and then delete this type.
	export type RequestAccessTokenResponse = {
		token_type: 'bearer';
		access_token: string;
		expires_in: number;
		refresh_token: string;
		scope: string;
		sub: string;
	};
	export type RefreshAccessTokenResponse = {
		token_type: 'bearer';
		access_token: string;
		expires_in: number;
		refresh_token: string;
		scope: string;
	};
	export type ListCalendarsResponse = {
		sub: string;
		calendars: Calendar[];
	};
	type _ReadEventsResponse = {
		pages: {
			current: number;
			total: number;
			next_page?: string;
		};
		events: Event[];
	};
	export type ReadEventsResponse = _ReadEventsResponse | WithUserInfo<_ReadEventsResponse>;
	export type DeleteEventResponse = void | WithUserInfo<{}>;
	export type CreateEventResponse = Event;

	// Atoms
	export type Calendar = {
		provider_name: ProviderName;
		profile_id: string;
		profile_name: string;
		calendar_id: string;
		calendar_name: string;
		calendar_readonly: boolean;
		calendar_deleted: boolean;
		calendar_primary: boolean;
		calendar_integrated_conferencing_available: boolean;
		calendar_attachments_available: boolean;
		permission_level: PermissionLevel;
	};
	export type Profile = {
		provider_name: ProviderName;
		provider_service: ProviderService;
		profile_id: string;
		profile_name: string;
		profile_connected: boolean;
		profile_initial_sync_required: boolean;
		profile_relink_url?: string; // Optional as it may not be present if the profile is connected
	};
	export type UserInfo = {
		sub: string;
		email?: string;
		name?: string;
		zoneinfo?: Timezone;
		'cronofy.type': string;
		'cronofy.data': {
			authorization: {
				scope: string;
				status: 'active' | 'hibernated';
				delegated_scope?: string; // Optional, for service accounts
			};
			profiles?: (Profile & {
				profile_calendars: Pick<
					Calendar,
					| 'calendar_id'
					| 'calendar_name'
					| 'calendar_readonly'
					| 'calendar_deleted'
					| 'calendar_primary'
					| 'calendar_integrated_conferencing_available'
					| 'calendar_attachments_available'
					| 'permission_level'
				>[];
			})[];
			application_calendar?: {
				application_calendar_id: string;
			};
			service_account?: {
				provider_name: string;
				domain?: string;
			};
		};
	};
	export type EventTimeInZone = {
		time: string;
		tzid: string;
	};
	export type Attendee = {
		email: string;
		display_name?: string;
	};
	export type Transparency = 'opaque' | 'transparent' | 'unknown';
	export type ExtendedTransparency = Transparency | 'working_elsewhere' | 'tentative' | 'out_of_office';
	export type Event = {
		calendar_id: string;
		event_uid: string;
		summary: string;
		description: string;
		start: string | EventTimeInZone;
		end: string | EventTimeInZone;
		url?: string;
		deleted: boolean;
		created: string;
		updated: string;
		location?: {
			description?: string;
			lat?: string;
			long?: string;
		};
		event_id?: string;
		participation_status: ParticipationStatus;
		attendees?: (Attendee & { partipation_status: ParticipationStatus })[];
		organizer?: {
			email?: string;
			display_name?: string;
		};
		transparency: Transparency;
		extended_transparency: ExtendedTransparency;
		status: 'tentative' | 'confirmed' | 'cancelled' | 'unknown';
		conferencing?: Pick<ConferencingInformation, 'provider_description' | 'join_url'>;
		meeting_url?: string;
		categories: string[];
		tags: Tags;
		attachments?: string[];
		recurring: boolean;
		series_identifier?: string;
		event_private: boolean;
		options: {
			delete: boolean;
			update: boolean;
			change_participation_status: boolean;
		};
	};
	export type Tags = { [context: string]: { value: string }[] };
	type BeforeTransition = {
		before: 'event_start' | 'event_end';
		offset: Duration;
	};
	type AfterTransition = {
		after: 'event_start' | 'event_end';
		offset: Duration;
	};
	export type Transition = BeforeTransition | AfterTransition;
	export type Duration = {
		minutes?: number;
		hours?: number;
	};
	export type Subscription = {
		type: 'webhook';
		uri: string;
		transitions: Transition[];
	};
	export type RecurrenceRule = {
		frequency: 'daily' | 'weekly' | 'monthly' | 'yearly';
		interval?: number;
		by_day?: { day: WeekDay }[]; // Used only with `weekly` frequency
		count?: number;
		until?: string; // Date string
	};
	export type ConferencingInformation = {
		profile_id: 'default' | 'explicit' | 'integrated' | 'none' | string; // string for custom profile IDs
		provider_description?: string; // Required if profile_id is 'explicit'
		join_url?: string; // Required if profile_id is 'explicit'
	};

	// Generics
	type WithUserInfo<T extends {}> = T & { userinfo: UserInfo };

	// Primitives
	type Timezone = string; // e.g. 'Europe/London' TODO - use a library for this
	type WeekDay = 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday';
	export type PermissionLevel = 'sandbox' | 'unrestricted';
	export type ProviderName = 'apple' | 'cronofy' | 'exchange' | 'google' | 'live_connect';
	export type ProviderService = 'cronofy' | 'exchange' | 'google' | 'gsuite' | 'icloud' | 'office365' | 'outlook_com';
	export type ParticipationStatus = 'needs_action' | 'accepted' | 'declined' | 'tentative' | 'unknown';
	export type DataCenter = 'au' | 'ca' | 'de' | 'sg' | 'uk' | 'us';
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants