From 85fe26d029d764fc19e969ef5136a1b8ddc0f96b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Yunus=20Sz=C3=B6nyi?= Date: Mon, 16 Mar 2026 21:12:09 +0100 Subject: [PATCH 1/4] feat(scheduler): add GET /v3/scheduling/availability endpoint support --- src/models/scheduler.ts | 23 +++++++++++++ src/resources/availability.ts | 34 +++++++++++++++++++ src/resources/scheduler.ts | 3 ++ tests/resources/availability.spec.ts | 50 ++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+) create mode 100644 src/resources/availability.ts create mode 100644 tests/resources/availability.spec.ts diff --git a/src/models/scheduler.ts b/src/models/scheduler.ts index a51d1588..521f5fbf 100644 --- a/src/models/scheduler.ts +++ b/src/models/scheduler.ts @@ -459,3 +459,26 @@ export interface FindBookingQueryParams { export type ConfirmBookingQueryParams = FindBookingQueryParams; export type RescheduleBookingQueryParams = FindBookingQueryParams; export type DestroyBookingQueryParams = FindBookingQueryParams; + +export interface AvailabilityTimeSlot { + emails: string[]; + startTime: number; + endTime: number; + eventId?: string; + masterId?: string; + calendarId?: string; +} + +export interface AvailabilityResponse { + order?: string[]; + timeSlots: AvailabilityTimeSlot[]; +} + +export interface GetAvailabilityQueryParams { + startTime: string; + endTime: string; + configurationId?: string; + slug?: string; + clientId?: string; + bookingId?: string; +} diff --git a/src/resources/availability.ts b/src/resources/availability.ts new file mode 100644 index 00000000..fdb7ef44 --- /dev/null +++ b/src/resources/availability.ts @@ -0,0 +1,34 @@ +import { Overrides } from '../config.js'; +import { NylasResponse } from '../models/response.js'; +import { + AvailabilityResponse, + GetAvailabilityQueryParams, +} from '../models/scheduler.js'; +import { Resource } from './resource.js'; +import { makePathParams } from '../utils.js'; + +/** + * The parameters for the {@link SchedulerAvailability.list} method + * @property queryParams The query parameters to include in the request + */ +export interface GetAvailabilityParams { + queryParams: GetAvailabilityQueryParams; +} + +export class SchedulerAvailability extends Resource { + /** + * Get availability for a scheduling configuration + * @return The availability response with time slots + */ + public list({ + queryParams, + overrides, + }: GetAvailabilityParams & + Overrides): Promise> { + return super._find({ + path: makePathParams('/v3/scheduling/availability', {}), + queryParams, + overrides, + }); + } +} diff --git a/src/resources/scheduler.ts b/src/resources/scheduler.ts index 397f5175..7c46b67e 100644 --- a/src/resources/scheduler.ts +++ b/src/resources/scheduler.ts @@ -1,16 +1,19 @@ import { Configurations } from './configurations.js'; import { Sessions } from './sessions.js'; import { Bookings } from './bookings.js'; +import { SchedulerAvailability } from './availability.js'; import APIClient from '../apiClient.js'; export class Scheduler { public configurations: Configurations; public bookings: Bookings; public sessions: Sessions; + public availability: SchedulerAvailability; constructor(apiClient: APIClient) { this.configurations = new Configurations(apiClient); this.bookings = new Bookings(apiClient); this.sessions = new Sessions(apiClient); + this.availability = new SchedulerAvailability(apiClient); } } diff --git a/tests/resources/availability.spec.ts b/tests/resources/availability.spec.ts new file mode 100644 index 00000000..655818c2 --- /dev/null +++ b/tests/resources/availability.spec.ts @@ -0,0 +1,50 @@ +import APIClient from '../../src/apiClient'; +import { SchedulerAvailability } from '../../src/resources/availability'; +jest.mock('../../src/apiClient'); + +describe('SchedulerAvailability', () => { + let apiClient: jest.Mocked; + let availability: SchedulerAvailability; + + beforeAll(() => { + apiClient = new APIClient({ + apiKey: 'apiKey', + apiUri: 'https://test.api.nylas.com', + timeout: 30, + headers: {}, + }) as jest.Mocked; + + availability = new SchedulerAvailability(apiClient); + apiClient.request.mockResolvedValue({}); + }); + + describe('list', () => { + it('should call apiClient.request with the correct params', async () => { + await availability.list({ + queryParams: { + startTime: '1659367800', + endTime: '1659369600', + configurationId: 'configuration123', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'foobar' }, + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/scheduling/availability', + queryParams: { + startTime: '1659367800', + endTime: '1659369600', + configurationId: 'configuration123', + }, + overrides: { + apiUri: 'https://test.api.nylas.com', + headers: { override: 'foobar' }, + }, + }); + }); + }); +}); From 091e518722a33a50316d9704e2edbbc27f97b56b Mon Sep 17 00:00:00 2001 From: Dan Radenkovic Date: Mon, 23 Mar 2026 15:01:09 +0100 Subject: [PATCH 2/4] fix(scheduler): address review issues in scheduling availability endpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Rename AvailabilityTimeSlot, AvailabilityResponse, and GetAvailabilityQueryParams with a Scheduler prefix to avoid naming collisions with the existing calendar availability types in src/models/availability.ts - Fix startTime/endTime in GetSchedulerAvailabilityQueryParams from string to number (unix timestamps) to match the AvailabilityTimeSlot fields and SDK conventions - Rename the public method from list() to get() since the endpoint returns a single AvailabilityResponse object, not a paginated list — internal delegation to _find() is unchanged - Update GetAvailabilityParams interface name to GetSchedulerAvailabilityParams - Expand test coverage from 1 to 5 cases: configurationId, slug, clientId, bookingId, and slug with special characters Made-with: Cursor --- src/models/scheduler.ts | 12 ++-- src/resources/availability.ts | 16 ++--- tests/resources/availability.spec.ts | 100 +++++++++++++++++++++++++-- 3 files changed, 107 insertions(+), 21 deletions(-) diff --git a/src/models/scheduler.ts b/src/models/scheduler.ts index 521f5fbf..b6268204 100644 --- a/src/models/scheduler.ts +++ b/src/models/scheduler.ts @@ -460,7 +460,7 @@ export type ConfirmBookingQueryParams = FindBookingQueryParams; export type RescheduleBookingQueryParams = FindBookingQueryParams; export type DestroyBookingQueryParams = FindBookingQueryParams; -export interface AvailabilityTimeSlot { +export interface SchedulerAvailabilityTimeSlot { emails: string[]; startTime: number; endTime: number; @@ -469,14 +469,14 @@ export interface AvailabilityTimeSlot { calendarId?: string; } -export interface AvailabilityResponse { +export interface SchedulerAvailabilityResponse { order?: string[]; - timeSlots: AvailabilityTimeSlot[]; + timeSlots: SchedulerAvailabilityTimeSlot[]; } -export interface GetAvailabilityQueryParams { - startTime: string; - endTime: string; +export interface GetSchedulerAvailabilityQueryParams { + startTime: number; + endTime: number; configurationId?: string; slug?: string; clientId?: string; diff --git a/src/resources/availability.ts b/src/resources/availability.ts index fdb7ef44..ca0770db 100644 --- a/src/resources/availability.ts +++ b/src/resources/availability.ts @@ -1,18 +1,18 @@ import { Overrides } from '../config.js'; import { NylasResponse } from '../models/response.js'; import { - AvailabilityResponse, - GetAvailabilityQueryParams, + SchedulerAvailabilityResponse, + GetSchedulerAvailabilityQueryParams, } from '../models/scheduler.js'; import { Resource } from './resource.js'; import { makePathParams } from '../utils.js'; /** - * The parameters for the {@link SchedulerAvailability.list} method + * The parameters for the {@link SchedulerAvailability.get} method * @property queryParams The query parameters to include in the request */ -export interface GetAvailabilityParams { - queryParams: GetAvailabilityQueryParams; +export interface GetSchedulerAvailabilityParams { + queryParams: GetSchedulerAvailabilityQueryParams; } export class SchedulerAvailability extends Resource { @@ -20,11 +20,11 @@ export class SchedulerAvailability extends Resource { * Get availability for a scheduling configuration * @return The availability response with time slots */ - public list({ + public get({ queryParams, overrides, - }: GetAvailabilityParams & - Overrides): Promise> { + }: GetSchedulerAvailabilityParams & + Overrides): Promise> { return super._find({ path: makePathParams('/v3/scheduling/availability', {}), queryParams, diff --git a/tests/resources/availability.spec.ts b/tests/resources/availability.spec.ts index 655818c2..1a39fd51 100644 --- a/tests/resources/availability.spec.ts +++ b/tests/resources/availability.spec.ts @@ -18,12 +18,12 @@ describe('SchedulerAvailability', () => { apiClient.request.mockResolvedValue({}); }); - describe('list', () => { - it('should call apiClient.request with the correct params', async () => { - await availability.list({ + describe('get', () => { + it('should call apiClient.request with configurationId', async () => { + await availability.get({ queryParams: { - startTime: '1659367800', - endTime: '1659369600', + startTime: 1659367800, + endTime: 1659369600, configurationId: 'configuration123', }, overrides: { @@ -36,8 +36,8 @@ describe('SchedulerAvailability', () => { method: 'GET', path: '/v3/scheduling/availability', queryParams: { - startTime: '1659367800', - endTime: '1659369600', + startTime: 1659367800, + endTime: 1659369600, configurationId: 'configuration123', }, overrides: { @@ -46,5 +46,91 @@ describe('SchedulerAvailability', () => { }, }); }); + + it('should call apiClient.request with slug', async () => { + await availability.get({ + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + slug: 'my-schedule', + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/scheduling/availability', + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + slug: 'my-schedule', + }, + overrides: undefined, + }); + }); + + it('should call apiClient.request with clientId', async () => { + await availability.get({ + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + clientId: 'client123', + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/scheduling/availability', + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + clientId: 'client123', + }, + overrides: undefined, + }); + }); + + it('should call apiClient.request with bookingId for reschedule availability', async () => { + await availability.get({ + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + configurationId: 'configuration123', + bookingId: 'booking456', + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/scheduling/availability', + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + configurationId: 'configuration123', + bookingId: 'booking456', + }, + overrides: undefined, + }); + }); + + it('should URL-encode special characters in query params', async () => { + await availability.get({ + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + slug: 'my schedule/special', + }, + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/scheduling/availability', + queryParams: { + startTime: 1659367800, + endTime: 1659369600, + slug: 'my schedule/special', + }, + overrides: undefined, + }); + }); }); }); From fb94d9a2db9d7719c5b90b3476b8fc4989d8e434 Mon Sep 17 00:00:00 2001 From: Dan Radenkovic Date: Mon, 23 Mar 2026 15:07:10 +0100 Subject: [PATCH 3/4] fix(tests): specify controller type in mock Web ReadableStream for attachments tests --- tests/resources/attachments.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/resources/attachments.spec.ts b/tests/resources/attachments.spec.ts index 3c068b58..b14d1ac8 100644 --- a/tests/resources/attachments.spec.ts +++ b/tests/resources/attachments.spec.ts @@ -20,7 +20,7 @@ describe('Attachments', () => { // Mock Web ReadableStream (native in Node 18+) const mockStream = new ReadableStream({ - start(controller) { + start(controller: ReadableStreamDefaultController): void { controller.enqueue(new Uint8Array([1, 2, 3])); controller.close(); }, From daaac3f453f6865a79eda7c28d409a9a161144d9 Mon Sep 17 00:00:00 2001 From: Dan Radenkovic Date: Mon, 23 Mar 2026 15:13:47 +0100 Subject: [PATCH 4/4] style: apply Prettier to scheduler availability resource Made-with: Cursor --- src/resources/availability.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/resources/availability.ts b/src/resources/availability.ts index ca0770db..79492541 100644 --- a/src/resources/availability.ts +++ b/src/resources/availability.ts @@ -23,8 +23,9 @@ export class SchedulerAvailability extends Resource { public get({ queryParams, overrides, - }: GetSchedulerAvailabilityParams & - Overrides): Promise> { + }: GetSchedulerAvailabilityParams & Overrides): Promise< + NylasResponse + > { return super._find({ path: makePathParams('/v3/scheduling/availability', {}), queryParams,