From 55b04e71c323956ef2e2bc94944827e2282b3572 Mon Sep 17 00:00:00 2001 From: Aaron de Mello Date: Fri, 17 Jan 2025 14:09:15 -0500 Subject: [PATCH] fix: transform anyEmail array into comma-delimited any_email parameter in threads list --- CHANGELOG.md | 1 + package-lock.json | 1 - src/apiClient.ts | 4 +++- src/resources/threads.ts | 12 +++++++++++- tests/apiClient.spec.ts | 18 +++++++++++++++++- tests/resources/threads.spec.ts | 23 +++++++++++++++++++++-- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84d203db..6a88661d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * Remove `createdAt` field from message model. * Change `latestMessageReceivedDate` & `latestMessageSentDate` to be optional on threads model. +* Fix issue where query params with array values were not being transformed into comma-delimited strings ### 7.7.2 / 2024-12-02 * Fix `credentials` resource to use correct endpoint. diff --git a/package-lock.json b/package-lock.json index 78ce4021..b34ab831 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "license": "MIT", "dependencies": { "change-case": "^4.1.2", - "eslint-plugin-import": "^2.28.1", "form-data": "^4.0.0", "mime-types": "^2.1.35", "node-fetch": "^2.6.12", diff --git a/src/apiClient.ts b/src/apiClient.ts index 1e118b3b..408c14d1 100644 --- a/src/apiClient.ts +++ b/src/apiClient.ts @@ -106,7 +106,9 @@ export default class APIClient { } url.searchParams.set('metadata_pair', metadataPair.join(',')); } else if (Array.isArray(value)) { - url.searchParams.append(snakeCaseKey, value.join(',')); + for (const item of value) { + url.searchParams.append(snakeCaseKey, item as string); + } } else if (typeof value === 'object') { for (const item in value) { url.searchParams.append( diff --git a/src/resources/threads.ts b/src/resources/threads.ts index f8675a68..550a5ac1 100644 --- a/src/resources/threads.ts +++ b/src/resources/threads.ts @@ -71,8 +71,18 @@ export class Threads extends Resource { }: ListThreadsParams & Overrides): AsyncListResponse< NylasListResponse > { + const modifiedQueryParams: Record | undefined = queryParams ? { ...queryParams } : undefined; + + // Transform some query params that are arrays into comma-delimited strings + if (modifiedQueryParams && queryParams) { + if (Array.isArray(queryParams?.anyEmail)) { + delete modifiedQueryParams.anyEmail; + modifiedQueryParams['any_email'] = queryParams.anyEmail.join(','); + } + } + return super._list>({ - queryParams, + queryParams: modifiedQueryParams, overrides, path: `/v3/grants/${identifier}/threads`, }); diff --git a/tests/apiClient.spec.ts b/tests/apiClient.spec.ts index 04a3a290..3685d3e4 100644 --- a/tests/apiClient.spec.ts +++ b/tests/apiClient.spec.ts @@ -114,7 +114,23 @@ describe('APIClient', () => { expect(options.url).toEqual( new URL( - 'https://api.us.nylas.com/test?foo=bar&list=a%2Cb%2Cc&map=key1%3Avalue1&map=key2%3Avalue2' + 'https://api.us.nylas.com/test?foo=bar&list=a&list=b&list=c&map=key1%3Avalue1&map=key2%3Avalue2' + ) + ); + }); + + it('should handle repeated query parameters', () => { + const options = client.requestOptions({ + path: '/test', + method: 'GET', + queryParams: { + eventType: ['default', 'outOfOffice', 'focusTime'], + }, + }); + + expect(options.url).toEqual( + new URL( + 'https://api.us.nylas.com/test?event_type=default&event_type=outOfOffice&event_type=focusTime' ) ); }); diff --git a/tests/resources/threads.spec.ts b/tests/resources/threads.spec.ts index 9507c414..8663c318 100644 --- a/tests/resources/threads.spec.ts +++ b/tests/resources/threads.spec.ts @@ -1,12 +1,12 @@ import APIClient from '../../src/apiClient'; import { Threads } from '../../src/resources/threads'; -jest.mock('../src/apiClient'); +jest.mock('../../src/apiClient'); describe('Threads', () => { let apiClient: jest.Mocked; let threads: Threads; - beforeAll(() => { + beforeEach(() => { apiClient = new APIClient({ apiKey: 'apiKey', apiUri: 'https://test.api.nylas.com', @@ -37,6 +37,25 @@ describe('Threads', () => { }, }); }); + + it('should transform anyEmail array into comma-delimited any_email parameter', async () => { + const mockEmails = ['test1@example.com', 'test2@example.com']; + await threads.list({ + identifier: 'id123', + queryParams: { + anyEmail: mockEmails + } + }); + + expect(apiClient.request).toHaveBeenCalledWith({ + method: 'GET', + path: '/v3/grants/id123/threads', + overrides: undefined, + queryParams: { + any_email: mockEmails.join(',') + } + }); + }); }); describe('find', () => {