Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Support for `trackingOptions` property in Message responses when using `fields=include_tracking_options`
- Support for `rawMime` property in Message responses when using `fields=raw_mime`
- `MessageTrackingOptions` interface for tracking message opens, thread replies, link clicks, and custom labels
- Support for `includeHiddenFolders` query parameter in folders list endpoint for Microsoft accounts
- Support for `singleLevel` query parameter in `ListFolderQueryParams` for Microsoft accounts to control folder hierarchy traversal

### Fixed
Expand Down
64 changes: 63 additions & 1 deletion examples/folders/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,65 @@
# Folders Example

This example demonstrates how to use the Nylas Node.js SDK to work with folders.

## Features Demonstrated

- List all folders for a grant
- Use the `includeHiddenFolders` parameter (Microsoft only) to include hidden folders in the response
- Filter folders by parent/child relationship
- Display folder attributes and metadata

## Setup

1. Copy `.env.example` to `.env` in the examples directory
2. Add your Nylas API credentials and grant ID:
```
NYLAS_API_KEY=your_api_key_here
NYLAS_GRANT_ID=your_grant_id_here
NYLAS_API_URI=https://api.us.nylas.com # or your specific Nylas region
```

## Running the Example

```bash
npm install
npm run folders
```

Or run directly with ts-node:
```bash
npx ts-node folders.ts
```

## Microsoft-Specific Features

The `includeHiddenFolders` parameter is specific to Microsoft accounts:

```typescript
const foldersWithHidden = await nylas.folders.list({
identifier: GRANT_ID,
queryParams: {
includeHiddenFolders: true, // Microsoft only - includes hidden folders
},
});
```

This parameter defaults to `false` and when set to `true`, includes folders that are typically hidden from the user interface, such as system folders used by Microsoft Exchange for internal operations.

## Expected Output

The example will output:
1. A list of all visible folders
2. A list of all folders including hidden ones (if using a Microsoft account)
3. A filtered list showing only parent folders with their metadata

## Error Handling

The example includes proper error handling and will display helpful error messages if:
- Environment variables are not set
- API requests fail
- Authentication issues occur
=======
# Nylas Folders API Examples

This directory contains examples of how to use the Nylas Folders API with the Nylas Node.js SDK, including the new `singleLevel` query parameter.
Expand Down Expand Up @@ -111,4 +173,4 @@ const allFolders = await nylas.folders.list({

## Documentation

For more information, see the [Nylas API Documentation](https://developer.nylas.com/).
For more information, see the [Nylas API Documentation](https://developer.nylas.com/).
91 changes: 90 additions & 1 deletion examples/folders/folders.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,92 @@
import 'dotenv/config';

import Nylas from '../../src/nylas';

const GRANT_ID = process.env.NYLAS_GRANT_ID || '';

const nylas = new Nylas({
apiKey: process.env.NYLAS_API_KEY || '',
apiUri: process.env.NYLAS_API_URI || 'https://api.us.nylas.com',
});

/**
* This example shows how to list folders using the Nylas Node.js SDK.
*
* For Microsoft accounts, you can use the includeHiddenFolders parameter
* to include hidden folders in the response.
*/
async function listFolders() {
try {
console.log('Listing all folders...\n');

// List all folders
const folders = await nylas.folders.list({
identifier: GRANT_ID,
});

console.log('Found', folders.data.length, 'folders');

folders.data.forEach((folder, index) => {
console.log(`${index + 1}. ${folder.name} (ID: ${folder.id})`);
if (folder.parentId) {
console.log(` Parent ID: ${folder.parentId}`);
}
if (folder.attributes && folder.attributes.length > 0) {
console.log(` Attributes: ${folder.attributes.join(', ')}`);
}
console.log('');
});

// For Microsoft accounts: List folders including hidden ones
console.log('\n--- Microsoft Only: Including Hidden Folders ---\n');

const foldersWithHidden = await nylas.folders.list({
identifier: GRANT_ID,
queryParams: {
includeHiddenFolders: true,
},
});

console.log('Found', foldersWithHidden.data.length, 'folders (including hidden)');

// List only parent folders (no parentId)
console.log('\n--- Parent Folders Only ---\n');

const parentFoldersWithHidden = await nylas.folders.list({
identifier: GRANT_ID,
queryParams: {
includeHiddenFolders: true,
},
});

const parentFolders = parentFoldersWithHidden.data.filter(folder => !folder.parentId);
console.log('Found', parentFolders.length, 'parent folders');

parentFolders.forEach((folder, index) => {
console.log(`${index + 1}. ${folder.name} (ID: ${folder.id})`);
if (folder.childCount) {
console.log(` Child folders: ${folder.childCount}`);
}
if (folder.totalCount) {
console.log(` Total items: ${folder.totalCount}`);
}
if (folder.unreadCount) {
console.log(` Unread items: ${folder.unreadCount}`);
}
console.log('');
});

} catch (error) {
console.error('Error listing folders:', error);
}
}

if (!GRANT_ID) {
console.error('Please set NYLAS_GRANT_ID in your environment variables');
} else {
listFolders().catch(console.error);
}
=======
import dotenv from 'dotenv';
import path from 'path';
import * as process from 'process';
Expand Down Expand Up @@ -215,4 +304,4 @@ if (require.main === module) {
main().catch(console.error);
}

export default main;
export default main;
5 changes: 5 additions & 0 deletions src/models/folders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ export interface ListFolderQueryParams extends ListQueryParams {
*/
parentId?: string;

/**
* (Microsoft only) When true, Nylas includes hidden folders in its response.
*/
includeHiddenFolders?: boolean;

/**
* (Microsoft only) If true, retrieves folders from a single-level hierarchy only.
* If false, retrieves folders across a multi-level hierarchy.
Expand Down
22 changes: 20 additions & 2 deletions tests/resources/folders.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('Folders', () => {
}) as jest.Mocked<APIClient>;

folders = new Folders(apiClient);
apiClient.request.mockResolvedValue({});
apiClient.request.mockResolvedValue({ data: [] });
});

describe('deserializing', () => {
Expand Down Expand Up @@ -78,6 +78,7 @@ describe('Folders', () => {
await folders.list({
identifier: 'id123',
queryParams: {
includeHiddenFolders: true,
singleLevel: true,
parentId: 'parent123',
},
Expand All @@ -91,6 +92,7 @@ describe('Folders', () => {
method: 'GET',
path: '/v3/grants/id123/folders',
queryParams: {
includeHiddenFolders: true,
singleLevel: true,
parentId: 'parent123',
},
Expand All @@ -101,20 +103,36 @@ describe('Folders', () => {
});
});

it('should call apiClient.request with single_level set to false', async () => {
it('should call apiClient.request with all supported query parameters', async () => {
await folders.list({
identifier: 'id123',
queryParams: {
parentId: 'parent123',
includeHiddenFolders: false,
limit: 10,
pageToken: 'token123',
singleLevel: false,
},
overrides: {
apiUri: 'https://test.api.nylas.com',
headers: { override: 'bar' },
},
});

expect(apiClient.request).toHaveBeenCalledWith({
method: 'GET',
path: '/v3/grants/id123/folders',
queryParams: {
parentId: 'parent123',
includeHiddenFolders: false,
limit: 10,
pageToken: 'token123',
singleLevel: false,
},
overrides: {
apiUri: 'https://test.api.nylas.com',
headers: { override: 'bar' },
},
});
});
});
Expand Down