Skip to content
Open
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
17 changes: 17 additions & 0 deletions .claude/instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,23 @@ Your job is to maintain parity with the API to ensure that the SDK supports all

When asked to add support for a new feature, query parameter, or API endpoint, follow this workflow:

### 0. Analyse Backward Compatibility FIRST (before proposing any plan)

Before writing a plan or touching any code, explicitly analyse whether the proposed changes are backward compatible for existing SDK consumers (both Kotlin and Java).

Check all of the following:
- **Source compatibility (Kotlin)**: Does changing a type (e.g. `String` → `String?`) break existing call sites that assume non-nullability?
- **Source compatibility (Java)**: Does the change affect compiled Java code that uses the SDK?
- **Binary compatibility (JVM)**: Does the bytecode signature of any public method change?
- **Constructor/data class compatibility**: Does changing a field's type or default break existing construction patterns?

If the change is **NOT** backward compatible, output this warning in your response before anything else:

> # ⚠️ WARNING: THIS CHANGE IS NOT BACKWARD COMPATIBLE ⚠️
> Existing SDK consumers will be broken. Do not proceed without explicit user approval or a backward-compatible alternative.

If a backward-compatible alternative exists (e.g. using `String = ""` instead of `String?` to keep Moshi happy while preserving non-nullability), prefer it and explain why.

### 1. Understand the Codebase
- Scan the project structure
- Understand the architecture and how it's organized
Expand Down
4 changes: 3 additions & 1 deletion .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"Bash(/usr/libexec/java_home:*)",
"Bash(./gradlew clean test:*)",
"Bash(./gradlew:*)",
"Bash(./gradlew build:*)"
"Bash(./gradlew build:*)",
"mcp__claude_ai_Atlassian__getJiraIssue",
"WebFetch(domain:developer.nylas.com)"
]
}
}
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Nylas Java SDK Changelog

## [Unreleased]

### Fixed
* `Folder.id` and `Folder.grantId` now default to empty strings so deserialization no longer fails when either field is absent from the API response due to the `select` query parameter

## [v2.15.1] - Release 2026-03-30

### Changed
Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/com/nylas/models/Folder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ data class Folder(
* A globally unique object identifier.
*/
@Json(name = "id")
val id: String,
val id: String = "",
/**
* A Grant ID of the Nylas account.
*/
@Json(name = "grant_id")
val grantId: String,
val grantId: String = "",
/**
* Folder name
*/
Expand Down
28 changes: 28 additions & 0 deletions src/test/kotlin/com/nylas/resources/FoldersTests.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,34 @@ class FoldersTests {
assertEquals(0, folder.totalCount)
assertEquals(listOf("\\SENT"), folder.attributes)
}

@Test
fun `Folder deserializes correctly when grant_id is absent due to select`() {
val adapter = JsonHelper.moshi().adapter(Folder::class.java)
val jsonBuffer = Buffer().writeUtf8(
"""{ "id": "SENT", "name": "SENT", "object": "folder" }""",
)

val folder = adapter.fromJson(jsonBuffer)!!
assertIs<Folder>(folder)
assertEquals("SENT", folder.id)
assertEquals("", folder.grantId)
assertEquals("SENT", folder.name)
}

@Test
fun `Folder deserializes correctly when both id and grant_id are absent due to select`() {
val adapter = JsonHelper.moshi().adapter(Folder::class.java)
val jsonBuffer = Buffer().writeUtf8(
"""{ "name": "SENT", "object": "folder" }""",
)

val folder = adapter.fromJson(jsonBuffer)!!
assertIs<Folder>(folder)
assertEquals("", folder.id)
assertEquals("", folder.grantId)
assertEquals("SENT", folder.name)
}
}

@Nested
Expand Down
Loading