From 12d72cb6dd20d12f63ea9d27e1eec5f546cec366 Mon Sep 17 00:00:00 2001 From: Aaron de Mello Date: Wed, 26 Feb 2025 21:26:06 -0500 Subject: [PATCH 1/4] Add support for listImportEvents method to import events from calendars This adds support for the new beta endpoint GET /v3/grants/{grant_id}/events/import, which allows importing events from a calendar within a specified time frame. This is useful for applications that need to synchronize events with their own calendaring solution or enrich events with custom data. --- CHANGELOG.md | 7 ++- src/models/events.ts | 35 +++++++++++++++ src/resources/events.ts | 27 +++++++++++ tests/resources/events.spec.ts | 82 ++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef9dd3da..fcb74c18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +### Unreleased +* Add support for `listImportEvents` method to import events from a specified calendar within a given time frame + ### 7.7.4 / 2025-01-23 * Fix: any_email was not transformed to a comma delimited list for messages.list @@ -91,7 +94,7 @@ * **BREAKING CHANGE**: Dropped the use of 'Collections' in favor of 'Resources' * **BREAKING CHANGE**: Removed all REST calls from models and moved them directly into resources * **REMOVED**: Local Webhook development support is removed due to incompatibility -* Rewrote the majority of SDK to be more modular and efficient +* Rewritten the majority of SDK to be more modular and efficient * Removed the use of custom strings for serialization and deserialization, now automatically converting to camelCase and from the API's snake_case * Added support for both ES6 and CommonJS module systems * Created models for all API resources and endpoints, for all HTTP methods to reduce confusion on which fields are available for each endpoint @@ -416,7 +419,7 @@ Note: version 4.2.1 was not released. * Added `upgrade()` and `downgrade()` for account management * Added `getRaw()` for retrieving raw messages * **BREAKING CHANGE**: Changed API for sending raw messages to use `draft.send()` instead of `Message.sendRaw()` -* Changed `list()` to override default `offset` with user’s +* Changed `list()` to override default `offset` with user's * **BREAKING CHANGE**: Changed models for `Contact`, `Draft`, `Event`, `File`, `Folder`, `Message`, and `Thread` to accurately reflect the attribute that the API returns * Return headers correctly for `expanded` view for `Message` objects * **BREAKING CHANGE**: Return `Message` object instead of `Draft` object after send diff --git a/src/models/events.ts b/src/models/events.ts index 038f451e..ca56cb97 100644 --- a/src/models/events.ts +++ b/src/models/events.ts @@ -333,6 +333,41 @@ export type DestroyEventQueryParams = CreateEventQueryParams; */ export type SendRsvpQueryParams = FindEventQueryParams; +/** + * Interface representing the query parameters for importing events. + */ +export interface ImportEventQueryParams { + /** + * (Required) Calendar ID to import events from. "primary" is a supported value indicating the user's primary calendar. + * Note: "primary" is not supported for iCloud. + */ + calendarId: string; + /** + * Filter for events that start at or after the specified time, in Unix timestamp format. + * Defaults to the time of the request. + */ + start?: number; + /** + * Filter for events that end at or before the specified time, in Unix timestamp format. + * Defaults to one month from the time of the request. + */ + end?: number; + /** + * The maximum number of objects to return. + * This field defaults to 50. The maximum allowed value is 500. + */ + max_results?: number; + /** + * An identifier that specifies which page of data to return. + * This value should be taken from the next_cursor response field. + */ + page_token?: string; + /** + * Specify fields that you want Nylas to return, as a comma-separated list. + */ + select?: string; +} + /** * Enum representing the status of an event. */ diff --git a/src/resources/events.ts b/src/resources/events.ts index 467f6e6a..354507d8 100644 --- a/src/resources/events.ts +++ b/src/resources/events.ts @@ -5,6 +5,7 @@ import { DestroyEventQueryParams, Event, FindEventQueryParams, + ImportEventQueryParams, ListEventQueryParams, SendRsvpQueryParams, SendRsvpRequest, @@ -74,6 +75,15 @@ export interface DestroyEventParams { queryParams: DestroyEventQueryParams; } +/** + * @property identifier The identifier of the grant to act upon + * @property queryParams The query parameters to include in the request + */ +export interface ListImportEventParams { + identifier: string; + queryParams: ImportEventQueryParams; +} + /** * @property identifier The identifier of the grant to act upon * @property eventId The id of the Event to update. @@ -109,6 +119,23 @@ export class Events extends Resource { }); } + /** + * (Beta) Import events from a calendar within a given time frame + * This is useful when you want to import, store, and synchronize events from the time frame to your application + * @return The list of imported Events + */ + public listImportEvents({ + identifier, + queryParams, + overrides, + }: ListImportEventParams & Overrides): AsyncListResponse> { + return super._list({ + queryParams, + path: `/v3/grants/${identifier}/events/import`, + overrides, + }); + } + /** * Return an Event * @return The Event diff --git a/tests/resources/events.spec.ts b/tests/resources/events.spec.ts index c8efef73..53a81f9c 100644 --- a/tests/resources/events.spec.ts +++ b/tests/resources/events.spec.ts @@ -128,6 +128,88 @@ describe('Events', () => { //TODO::More iterator tests }); + describe('listImportEvents', () => { + it('should call apiClient.request with the correct params', async () => { + await events.listImportEvents({ + identifier: 'id123', + queryParams: { + calendarId: 'calendar123', + start: 1617235200, + end: 1619827200, + max_results: 100, + select: 'id,name', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'bar' }, + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/grants/id123/events/import', + queryParams: { + calendarId: 'calendar123', + start: 1617235200, + end: 1619827200, + max_results: 100, + select: 'id,name', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'bar' }, + }, + }); + }); + + it('should paginate correctly with page_token for import events', async () => { + apiClient.request.mockResolvedValueOnce({ + requestId: 'request123', + data: [ + { + id: 'id', + name: 'name', + }, + ], + nextCursor: 'cursor123', + }); + const eventList = await events.listImportEvents({ + identifier: 'id123', + queryParams: { + calendarId: 'calendar123', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'bar' }, + }, + }); + apiClient.request.mockResolvedValueOnce({ + requestId: 'request123', + data: [ + { + id: 'id', + name: 'name', + }, + ], + }); + await eventList.next(); + + expect(apiClient.request).toBeCalledTimes(2); + expect(apiClient.request).toHaveBeenLastCalledWith({ + method: 'GET', + path: '/v3/grants/id123/events/import', + queryParams: { + calendarId: 'calendar123', + pageToken: 'cursor123', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'bar' }, + }, + }); + }); + }); + describe('find', () => { it('should call apiClient.request with the correct params', async () => { await events.find({ From 4a8bd3a856f7cebf466fd25f1a9aeb6ab3da0f97 Mon Sep 17 00:00:00 2001 From: Aaron de Mello Date: Wed, 26 Feb 2025 21:29:57 -0500 Subject: [PATCH 2/4] Rename ImportEventQueryParams to ListImportEventQueryParams for consistency --- src/models/events.ts | 2 +- src/resources/events.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/models/events.ts b/src/models/events.ts index ca56cb97..bab348e6 100644 --- a/src/models/events.ts +++ b/src/models/events.ts @@ -336,7 +336,7 @@ export type SendRsvpQueryParams = FindEventQueryParams; /** * Interface representing the query parameters for importing events. */ -export interface ImportEventQueryParams { +export interface ListImportEventQueryParams { /** * (Required) Calendar ID to import events from. "primary" is a supported value indicating the user's primary calendar. * Note: "primary" is not supported for iCloud. diff --git a/src/resources/events.ts b/src/resources/events.ts index 354507d8..a6e7f22b 100644 --- a/src/resources/events.ts +++ b/src/resources/events.ts @@ -5,7 +5,7 @@ import { DestroyEventQueryParams, Event, FindEventQueryParams, - ImportEventQueryParams, + ListImportEventQueryParams, ListEventQueryParams, SendRsvpQueryParams, SendRsvpRequest, @@ -81,7 +81,7 @@ export interface DestroyEventParams { */ export interface ListImportEventParams { identifier: string; - queryParams: ImportEventQueryParams; + queryParams: ListImportEventQueryParams; } /** From c519a0901b94911b4e61b91aa343e127f51a19b2 Mon Sep 17 00:00:00 2001 From: Aaron de Mello Date: Thu, 27 Feb 2025 22:25:40 -0500 Subject: [PATCH 3/4] Renamed max_results to limit for listImportEvents --- src/models/events.ts | 16 +--------------- tests/resources/events.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/models/events.ts b/src/models/events.ts index bab348e6..626f449b 100644 --- a/src/models/events.ts +++ b/src/models/events.ts @@ -336,7 +336,7 @@ export type SendRsvpQueryParams = FindEventQueryParams; /** * Interface representing the query parameters for importing events. */ -export interface ListImportEventQueryParams { +export interface ListImportEventQueryParams extends ListQueryParams { /** * (Required) Calendar ID to import events from. "primary" is a supported value indicating the user's primary calendar. * Note: "primary" is not supported for iCloud. @@ -352,20 +352,6 @@ export interface ListImportEventQueryParams { * Defaults to one month from the time of the request. */ end?: number; - /** - * The maximum number of objects to return. - * This field defaults to 50. The maximum allowed value is 500. - */ - max_results?: number; - /** - * An identifier that specifies which page of data to return. - * This value should be taken from the next_cursor response field. - */ - page_token?: string; - /** - * Specify fields that you want Nylas to return, as a comma-separated list. - */ - select?: string; } /** diff --git a/tests/resources/events.spec.ts b/tests/resources/events.spec.ts index 53a81f9c..7b2aac6b 100644 --- a/tests/resources/events.spec.ts +++ b/tests/resources/events.spec.ts @@ -136,7 +136,7 @@ describe('Events', () => { calendarId: 'calendar123', start: 1617235200, end: 1619827200, - max_results: 100, + limit: 100, select: 'id,name', }, overrides: { @@ -152,7 +152,7 @@ describe('Events', () => { calendarId: 'calendar123', start: 1617235200, end: 1619827200, - max_results: 100, + limit: 100, select: 'id,name', }, overrides: { From cca658bf13c2b158d9730fc44f32404a991677a9 Mon Sep 17 00:00:00 2001 From: Aaron de Mello Date: Mon, 3 Mar 2025 10:49:25 -0500 Subject: [PATCH 4/4] Ran prettier --- src/models/events.ts | 2 +- src/resources/events.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/models/events.ts b/src/models/events.ts index 626f449b..a8ac48d6 100644 --- a/src/models/events.ts +++ b/src/models/events.ts @@ -336,7 +336,7 @@ export type SendRsvpQueryParams = FindEventQueryParams; /** * Interface representing the query parameters for importing events. */ -export interface ListImportEventQueryParams extends ListQueryParams { +export interface ListImportEventQueryParams extends ListQueryParams { /** * (Required) Calendar ID to import events from. "primary" is a supported value indicating the user's primary calendar. * Note: "primary" is not supported for iCloud. diff --git a/src/resources/events.ts b/src/resources/events.ts index a6e7f22b..f9cbc971 100644 --- a/src/resources/events.ts +++ b/src/resources/events.ts @@ -128,7 +128,9 @@ export class Events extends Resource { identifier, queryParams, overrides, - }: ListImportEventParams & Overrides): AsyncListResponse> { + }: ListImportEventParams & Overrides): AsyncListResponse< + NylasListResponse + > { return super._list({ queryParams, path: `/v3/grants/${identifier}/events/import`,