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
@@ -1,6 +1,7 @@
# Changelog

### [Unreleased]
* Added support for `single_level` query parameter in Folders API for Microsoft accounts
* 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

### 6.5.0 / 2025-06-13
Expand Down
189 changes: 189 additions & 0 deletions examples/folders/folders_example.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

# Example demonstrating the single_level query parameter in the Nylas Ruby SDK Folders API
#
# This example shows how to:
# 1. List folders with default multi-level hierarchy
# 2. List folders with single-level hierarchy (Microsoft accounts only)
# 3. Combine single_level with other query parameters
#
# Prerequisites:
# - Ruby 3.0 or later
# - A Nylas API key
# - A grant ID (connected email account, preferably Microsoft for full functionality)
#
# Environment variables needed:
# export NYLAS_API_KEY="your_api_key"
# export NYLAS_GRANT_ID="your_grant_id"
# export NYLAS_API_URI="https://api.us.nylas.com" # Optional
#
# Alternatively, create a .env file in the examples directory with:
# NYLAS_API_KEY=your_api_key
# NYLAS_GRANT_ID=your_grant_id
# NYLAS_API_URI=https://api.us.nylas.com

$LOAD_PATH.unshift File.expand_path("../../lib", __dir__)
require "nylas"
require "json"

# Simple .env file loader
def load_env_file
env_file = File.expand_path("../.env", __dir__)
return unless File.exist?(env_file)

puts "Loading environment variables from .env file..."
File.readlines(env_file).each do |line|
line = line.strip
next if line.empty? || line.start_with?("#")

key, value = line.split("=", 2)
next unless key && value

# Remove quotes if present
value = value.gsub(/\A['"]|['"]\z/, "")
ENV[key] = value
end
end

def list_folders_multi_level(nylas, grant_id)
puts "\n=== Listing Folders with Multi-Level Hierarchy (Default) ==="

folders, request_id, next_cursor = nylas.folders.list(
identifier: grant_id
)

puts "Found #{folders.length} folders in multi-level hierarchy"
display_folders(folders)
puts "Request ID: #{request_id}"
puts "Next cursor: #{next_cursor || 'None'}"

folders
end

def list_folders_single_level(nylas, grant_id)
puts "\n=== Listing Folders with Single-Level Hierarchy (Microsoft Only) ==="

folders, request_id, next_cursor = nylas.folders.list(
identifier: grant_id,
query_params: { single_level: true }
)

puts "Found #{folders.length} folders in single-level hierarchy"
display_folders(folders)
puts "Request ID: #{request_id}"
puts "Next cursor: #{next_cursor || 'None'}"

folders
end

def list_folders_with_additional_params(nylas, grant_id)
puts "\n=== Listing Folders with Single-Level + Additional Parameters ==="

folders, request_id, next_cursor = nylas.folders.list(
identifier: grant_id,
query_params: {
single_level: true,
limit: 5
}
)

puts "Found #{folders.length} folders (limited to 5) in single-level hierarchy"
display_folders(folders)
puts "Request ID: #{request_id}"
puts "Next cursor: #{next_cursor || 'None'}"

folders
end

def display_folders(folders)
if folders.empty?
puts " No folders found"
return
end

folders.each do |folder|
parent_info = folder[:parent_id] ? "Parent: #{folder[:parent_id]}" : "Root folder"
system_folder = folder[:system_folder] ? " (System)" : ""
puts " - #{folder[:name]}#{system_folder}"
puts " ID: #{folder[:id]}"
puts " #{parent_info}"
puts " Unread: #{folder[:unread_count] || 0}, Total: #{folder[:total_count] || 0}"
puts
end
end

def demonstrate_single_level_parameter
puts "\n=== Single-Level Parameter Documentation ==="
puts "The single_level parameter is designed for Microsoft accounts and controls folder hierarchy:"
puts "- single_level: true -> Retrieves folders from a single-level hierarchy only"
puts "- single_level: false -> Retrieves folders across a multi-level hierarchy (default)"
puts "- This parameter is most effective with Microsoft Exchange/Outlook accounts"
puts "- Other providers may not show significant differences in behavior"
end

def main
# Load .env file if it exists
load_env_file

# Check for required environment variables
api_key = ENV["NYLAS_API_KEY"]
grant_id = ENV["NYLAS_GRANT_ID"]

raise "NYLAS_API_KEY environment variable is not set" unless api_key
raise "NYLAS_GRANT_ID environment variable is not set" unless grant_id

puts "Using API key: #{api_key[0..4]}..."
puts "Using grant ID: #{grant_id[0..8]}..."

# Initialize the Nylas client
nylas = Nylas::Client.new(
api_key: api_key,
api_uri: ENV["NYLAS_API_URI"] || "https://api.us.nylas.com"
)

puts "\n=== Nylas Folders Single-Level Parameter Example ==="

begin
# Demonstrate the parameter concept
demonstrate_single_level_parameter

# Example 1: List folders with default multi-level hierarchy
multi_level_folders = list_folders_multi_level(nylas, grant_id)

# Example 2: List folders with single-level hierarchy
single_level_folders = list_folders_single_level(nylas, grant_id)

# Example 3: List folders with single-level and additional parameters
list_folders_with_additional_params(nylas, grant_id)

# Compare results if both calls returned folders
if multi_level_folders.any? && single_level_folders.any?
puts "\n=== Comparison ==="
puts "Multi-level hierarchy returned: #{multi_level_folders.length} folders"
puts "Single-level hierarchy returned: #{single_level_folders.length} folders"

if multi_level_folders.length != single_level_folders.length
puts "Different folder counts suggest the single_level parameter is working as expected."
else
puts "Same folder count - this might indicate:"
puts "- The account doesn't have nested folders"
puts "- The provider doesn't support hierarchical folders"
puts "- The account is not a Microsoft account"
end
end
rescue StandardError => e
puts "\nError occurred: #{e.message}"
puts "This might happen if:"
puts "- The API key or grant ID is invalid"
puts "- The account doesn't have permission to access folders"
puts "- Network connectivity issues"
puts "\nFull error details:"
puts e.inspect
end

puts "\n=== Example completed ==="
end

# Run the example if this file is executed directly
main if __FILE__ == $PROGRAM_NAME
4 changes: 4 additions & 0 deletions lib/nylas/resources/folders.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ class Folders < Resource
#
# @param identifier [String] Grant ID or email account to query.
# @param query_params [Hash, nil] Query params to pass to the request.
# Supported parameters include:
# - single_level: (Boolean) For Microsoft accounts only. If true, retrieves folders from
# a single-level hierarchy only. If false (default), retrieves folders across a
# multi-level hierarchy.
# - include_hidden_folders [Boolean] (Microsoft only) When true, includes hidden folders.
# @return [Array(Array(Hash), String, String)] The list of folders, API Request ID, and next cursor.
def list(identifier:, query_params: nil)
Expand Down
30 changes: 28 additions & 2 deletions spec/nylas/resources/folders_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,35 @@
expect(folders_response).to eq(list_response)
end

it "calls the get method with the correct query parameters including include_hidden_folders" do
it "calls the get method with query parameters including single_level" do
identifier = "abc-123-grant-id"
query_params = { include_hidden_folders: true }
query_params = { single_level: true }
path = "#{api_uri}/v3/grants/#{identifier}/folders"
allow(folders).to receive(:get_list)
.with(path: path, query_params: query_params)
.and_return(list_response)

folders_response = folders.list(identifier: identifier, query_params: query_params)

expect(folders_response).to eq(list_response)
end

it "calls the get method with query parameters including single_level set to false" do
identifier = "abc-123-grant-id"
query_params = { single_level: false }
path = "#{api_uri}/v3/grants/#{identifier}/folders"
allow(folders).to receive(:get_list)
.with(path: path, query_params: query_params)
.and_return(list_response)

folders_response = folders.list(identifier: identifier, query_params: query_params)

expect(folders_response).to eq(list_response)
end

it "calls the get method with multiple query parameters including single_level" do
identifier = "abc-123-grant-id"
query_params = { single_level: true, limit: 10, include_hidden_folders: true }
path = "#{api_uri}/v3/grants/#{identifier}/folders"
allow(folders).to receive(:get_list)
.with(path: path, query_params: query_params)
Expand Down
Loading