Skip to content

Commit c35e81e

Browse files
authored
feat: add single_level query parameter support for Folders list endpoint (#527)
1 parent 1b78b3f commit c35e81e

File tree

4 files changed

+222
-2
lines changed

4 files changed

+222
-2
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Changelog
22

33
### [Unreleased]
4+
* Added support for `single_level` query parameter in Folders API for Microsoft accounts
45
* Added support for `include_hidden_folders` query parameter in folders list endpoint for Microsoft accounts to control whether hidden folders are included in the response
56

67
### 6.5.0 / 2025-06-13
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
# Example demonstrating the single_level query parameter in the Nylas Ruby SDK Folders API
5+
#
6+
# This example shows how to:
7+
# 1. List folders with default multi-level hierarchy
8+
# 2. List folders with single-level hierarchy (Microsoft accounts only)
9+
# 3. Combine single_level with other query parameters
10+
#
11+
# Prerequisites:
12+
# - Ruby 3.0 or later
13+
# - A Nylas API key
14+
# - A grant ID (connected email account, preferably Microsoft for full functionality)
15+
#
16+
# Environment variables needed:
17+
# export NYLAS_API_KEY="your_api_key"
18+
# export NYLAS_GRANT_ID="your_grant_id"
19+
# export NYLAS_API_URI="https://api.us.nylas.com" # Optional
20+
#
21+
# Alternatively, create a .env file in the examples directory with:
22+
# NYLAS_API_KEY=your_api_key
23+
# NYLAS_GRANT_ID=your_grant_id
24+
# NYLAS_API_URI=https://api.us.nylas.com
25+
26+
$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
27+
require "nylas"
28+
require "json"
29+
30+
# Simple .env file loader
31+
def load_env_file
32+
env_file = File.expand_path("../.env", __dir__)
33+
return unless File.exist?(env_file)
34+
35+
puts "Loading environment variables from .env file..."
36+
File.readlines(env_file).each do |line|
37+
line = line.strip
38+
next if line.empty? || line.start_with?("#")
39+
40+
key, value = line.split("=", 2)
41+
next unless key && value
42+
43+
# Remove quotes if present
44+
value = value.gsub(/\A['"]|['"]\z/, "")
45+
ENV[key] = value
46+
end
47+
end
48+
49+
def list_folders_multi_level(nylas, grant_id)
50+
puts "\n=== Listing Folders with Multi-Level Hierarchy (Default) ==="
51+
52+
folders, request_id, next_cursor = nylas.folders.list(
53+
identifier: grant_id
54+
)
55+
56+
puts "Found #{folders.length} folders in multi-level hierarchy"
57+
display_folders(folders)
58+
puts "Request ID: #{request_id}"
59+
puts "Next cursor: #{next_cursor || 'None'}"
60+
61+
folders
62+
end
63+
64+
def list_folders_single_level(nylas, grant_id)
65+
puts "\n=== Listing Folders with Single-Level Hierarchy (Microsoft Only) ==="
66+
67+
folders, request_id, next_cursor = nylas.folders.list(
68+
identifier: grant_id,
69+
query_params: { single_level: true }
70+
)
71+
72+
puts "Found #{folders.length} folders in single-level hierarchy"
73+
display_folders(folders)
74+
puts "Request ID: #{request_id}"
75+
puts "Next cursor: #{next_cursor || 'None'}"
76+
77+
folders
78+
end
79+
80+
def list_folders_with_additional_params(nylas, grant_id)
81+
puts "\n=== Listing Folders with Single-Level + Additional Parameters ==="
82+
83+
folders, request_id, next_cursor = nylas.folders.list(
84+
identifier: grant_id,
85+
query_params: {
86+
single_level: true,
87+
limit: 5
88+
}
89+
)
90+
91+
puts "Found #{folders.length} folders (limited to 5) in single-level hierarchy"
92+
display_folders(folders)
93+
puts "Request ID: #{request_id}"
94+
puts "Next cursor: #{next_cursor || 'None'}"
95+
96+
folders
97+
end
98+
99+
def display_folders(folders)
100+
if folders.empty?
101+
puts " No folders found"
102+
return
103+
end
104+
105+
folders.each do |folder|
106+
parent_info = folder[:parent_id] ? "Parent: #{folder[:parent_id]}" : "Root folder"
107+
system_folder = folder[:system_folder] ? " (System)" : ""
108+
puts " - #{folder[:name]}#{system_folder}"
109+
puts " ID: #{folder[:id]}"
110+
puts " #{parent_info}"
111+
puts " Unread: #{folder[:unread_count] || 0}, Total: #{folder[:total_count] || 0}"
112+
puts
113+
end
114+
end
115+
116+
def demonstrate_single_level_parameter
117+
puts "\n=== Single-Level Parameter Documentation ==="
118+
puts "The single_level parameter is designed for Microsoft accounts and controls folder hierarchy:"
119+
puts "- single_level: true -> Retrieves folders from a single-level hierarchy only"
120+
puts "- single_level: false -> Retrieves folders across a multi-level hierarchy (default)"
121+
puts "- This parameter is most effective with Microsoft Exchange/Outlook accounts"
122+
puts "- Other providers may not show significant differences in behavior"
123+
end
124+
125+
def main
126+
# Load .env file if it exists
127+
load_env_file
128+
129+
# Check for required environment variables
130+
api_key = ENV["NYLAS_API_KEY"]
131+
grant_id = ENV["NYLAS_GRANT_ID"]
132+
133+
raise "NYLAS_API_KEY environment variable is not set" unless api_key
134+
raise "NYLAS_GRANT_ID environment variable is not set" unless grant_id
135+
136+
puts "Using API key: #{api_key[0..4]}..."
137+
puts "Using grant ID: #{grant_id[0..8]}..."
138+
139+
# Initialize the Nylas client
140+
nylas = Nylas::Client.new(
141+
api_key: api_key,
142+
api_uri: ENV["NYLAS_API_URI"] || "https://api.us.nylas.com"
143+
)
144+
145+
puts "\n=== Nylas Folders Single-Level Parameter Example ==="
146+
147+
begin
148+
# Demonstrate the parameter concept
149+
demonstrate_single_level_parameter
150+
151+
# Example 1: List folders with default multi-level hierarchy
152+
multi_level_folders = list_folders_multi_level(nylas, grant_id)
153+
154+
# Example 2: List folders with single-level hierarchy
155+
single_level_folders = list_folders_single_level(nylas, grant_id)
156+
157+
# Example 3: List folders with single-level and additional parameters
158+
list_folders_with_additional_params(nylas, grant_id)
159+
160+
# Compare results if both calls returned folders
161+
if multi_level_folders.any? && single_level_folders.any?
162+
puts "\n=== Comparison ==="
163+
puts "Multi-level hierarchy returned: #{multi_level_folders.length} folders"
164+
puts "Single-level hierarchy returned: #{single_level_folders.length} folders"
165+
166+
if multi_level_folders.length != single_level_folders.length
167+
puts "Different folder counts suggest the single_level parameter is working as expected."
168+
else
169+
puts "Same folder count - this might indicate:"
170+
puts "- The account doesn't have nested folders"
171+
puts "- The provider doesn't support hierarchical folders"
172+
puts "- The account is not a Microsoft account"
173+
end
174+
end
175+
rescue StandardError => e
176+
puts "\nError occurred: #{e.message}"
177+
puts "This might happen if:"
178+
puts "- The API key or grant ID is invalid"
179+
puts "- The account doesn't have permission to access folders"
180+
puts "- Network connectivity issues"
181+
puts "\nFull error details:"
182+
puts e.inspect
183+
end
184+
185+
puts "\n=== Example completed ==="
186+
end
187+
188+
# Run the example if this file is executed directly
189+
main if __FILE__ == $PROGRAM_NAME

lib/nylas/resources/folders.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ class Folders < Resource
1515
#
1616
# @param identifier [String] Grant ID or email account to query.
1717
# @param query_params [Hash, nil] Query params to pass to the request.
18+
# Supported parameters include:
19+
# - single_level: (Boolean) For Microsoft accounts only. If true, retrieves folders from
20+
# a single-level hierarchy only. If false (default), retrieves folders across a
21+
# multi-level hierarchy.
1822
# - include_hidden_folders [Boolean] (Microsoft only) When true, includes hidden folders.
1923
# @return [Array(Array(Hash), String, String)] The list of folders, API Request ID, and next cursor.
2024
def list(identifier:, query_params: nil)

spec/nylas/resources/folders_spec.rb

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,35 @@
3535
expect(folders_response).to eq(list_response)
3636
end
3737

38-
it "calls the get method with the correct query parameters including include_hidden_folders" do
38+
it "calls the get method with query parameters including single_level" do
3939
identifier = "abc-123-grant-id"
40-
query_params = { include_hidden_folders: true }
40+
query_params = { single_level: true }
41+
path = "#{api_uri}/v3/grants/#{identifier}/folders"
42+
allow(folders).to receive(:get_list)
43+
.with(path: path, query_params: query_params)
44+
.and_return(list_response)
45+
46+
folders_response = folders.list(identifier: identifier, query_params: query_params)
47+
48+
expect(folders_response).to eq(list_response)
49+
end
50+
51+
it "calls the get method with query parameters including single_level set to false" do
52+
identifier = "abc-123-grant-id"
53+
query_params = { single_level: false }
54+
path = "#{api_uri}/v3/grants/#{identifier}/folders"
55+
allow(folders).to receive(:get_list)
56+
.with(path: path, query_params: query_params)
57+
.and_return(list_response)
58+
59+
folders_response = folders.list(identifier: identifier, query_params: query_params)
60+
61+
expect(folders_response).to eq(list_response)
62+
end
63+
64+
it "calls the get method with multiple query parameters including single_level" do
65+
identifier = "abc-123-grant-id"
66+
query_params = { single_level: true, limit: 10, include_hidden_folders: true }
4167
path = "#{api_uri}/v3/grants/#{identifier}/folders"
4268
allow(folders).to receive(:get_list)
4369
.with(path: path, query_params: query_params)

0 commit comments

Comments
 (0)