- 
                Notifications
    
You must be signed in to change notification settings  - Fork 22
 
feat: .NET SDK update for version 0.21.2 #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
          
WalkthroughVersion bumped from 0.21.1 to 0.21.2 (Appwrite.csproj) and client default headers updated ( Pre-merge checks and finishing touches❌ Failed checks (1 warning)
 ✅ Passed checks (2 passed)
 ✨ Finishing touches
 🧪 Generate unit tests (beta)
 Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment   | 
    
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR updates the .NET SDK from version 0.21.1 to 0.21.2, focusing on improving array deserialization to correctly handle mixed/object arrays. The change replaces complex conditional deserialization logic with a unified ConvertToList<T> extension method across all model classes.
- Updated version references in documentation, configuration, and client headers
 - Introduced a new 
ConvertToList<T>extension method to handle various array types includingObject[],JsonElement, and standard collections - Refactored array deserialization across all model classes from complex conditional logic to simplified extension method calls
 
Reviewed Changes
Copilot reviewed 127 out of 127 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description | 
|---|---|
| README.md | Updated package version references from 0.21.1 to 0.21.2 | 
| CHANGELOG.md | Added changelog entry documenting the array deserialization fix | 
| Appwrite/Extensions/Extensions.cs | Added new ConvertToList<T> extension method to handle mixed array types | 
| Appwrite/Client.cs | Updated SDK version in user-agent and SDK version headers | 
| Appwrite/Appwrite.csproj | Bumped package version to 0.21.2 | 
| Appwrite/Models/*.cs | Replaced complex array deserialization logic with unified ConvertToList<T> calls and added extension import | 
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 11
🧹 Nitpick comments (4)
Appwrite/Models/ResourceTokenList.cs (1)
30-31: Guard tokens conversion; default to empty listIf map["tokens"] is missing/null, this will throw. Safer to fallback to [].
Apply:
- tokens: map["tokens"].ConvertToList<Dictionary<string, object>>().Select(it => ResourceToken.From(map: it)).ToList() + tokens: (map.TryGetValue("tokens", out var tokensObj) && tokensObj != null + ? tokensObj.ConvertToList<Dictionary<string, object>>() + : new List<Dictionary<string, object>>() + ).Select(it => ResourceToken.From(map: it)).ToList()Do API responses always include "tokens" as an array (possibly empty)? If yes, the current code is fine; otherwise, consider the guard above.
Appwrite/Models/AlgoMd5.cs (1)
8-8: Unused import.The
using Appwrite.Extensions;directive is added but not used in this file. Neither theFromnorToMapmethods utilize any extension methods.Apply this diff to remove the unused import:
using System.Text.Json.Serialization; using Appwrite.Enums; -using Appwrite.Extensions; namespace Appwrite.ModelsAppwrite/Models/Row.cs (1)
64-66: Make$permissionsextraction null/omission-safeGuard against missing or null
$permissions(and JsonElement.Null) to prevent KeyNotFound/InvalidCast:- permissions: map["$permissions"].ConvertToList<string>(), + permissions: (map.TryGetValue("$permissions", out var p) && p is not JsonElement { ValueKind: JsonValueKind.Null } && p != null) + ? p.ConvertToList<string>() + : new List<string>(),Appwrite/Models/Specification.cs (1)
8-8: Remove unused import.The
using Appwrite.Extensions;directive is added butConvertToList<T>()is not used anywhere in this file. TheFrommethod only performs scalar conversions.Apply this diff to remove the unused import:
-using Appwrite.Extensions;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (107)
Appwrite/Extensions/Extensions.cs(2 hunks)Appwrite/Models/AlgoArgon2.cs(1 hunks)Appwrite/Models/AlgoBcrypt.cs(1 hunks)Appwrite/Models/AlgoMd5.cs(1 hunks)Appwrite/Models/AlgoPhpass.cs(1 hunks)Appwrite/Models/AlgoScrypt.cs(1 hunks)Appwrite/Models/AlgoScryptModified.cs(1 hunks)Appwrite/Models/AlgoSha.cs(1 hunks)Appwrite/Models/AttributeBoolean.cs(1 hunks)Appwrite/Models/AttributeDatetime.cs(1 hunks)Appwrite/Models/AttributeEmail.cs(1 hunks)Appwrite/Models/AttributeEnum.cs(2 hunks)Appwrite/Models/AttributeFloat.cs(1 hunks)Appwrite/Models/AttributeInteger.cs(1 hunks)Appwrite/Models/AttributeIp.cs(1 hunks)Appwrite/Models/AttributeLine.cs(2 hunks)Appwrite/Models/AttributeList.cs(2 hunks)Appwrite/Models/AttributePoint.cs(2 hunks)Appwrite/Models/AttributePolygon.cs(2 hunks)Appwrite/Models/AttributeRelationship.cs(1 hunks)Appwrite/Models/AttributeString.cs(1 hunks)Appwrite/Models/AttributeUrl.cs(1 hunks)Appwrite/Models/Bucket.cs(2 hunks)Appwrite/Models/BucketList.cs(2 hunks)Appwrite/Models/Collection.cs(2 hunks)Appwrite/Models/CollectionList.cs(2 hunks)Appwrite/Models/ColumnBoolean.cs(1 hunks)Appwrite/Models/ColumnDatetime.cs(1 hunks)Appwrite/Models/ColumnEmail.cs(1 hunks)Appwrite/Models/ColumnEnum.cs(2 hunks)Appwrite/Models/ColumnFloat.cs(1 hunks)Appwrite/Models/ColumnIndex.cs(2 hunks)Appwrite/Models/ColumnIndexList.cs(2 hunks)Appwrite/Models/ColumnInteger.cs(1 hunks)Appwrite/Models/ColumnIp.cs(1 hunks)Appwrite/Models/ColumnLine.cs(2 hunks)Appwrite/Models/ColumnList.cs(2 hunks)Appwrite/Models/ColumnPoint.cs(2 hunks)Appwrite/Models/ColumnPolygon.cs(2 hunks)Appwrite/Models/ColumnRelationship.cs(1 hunks)Appwrite/Models/ColumnString.cs(1 hunks)Appwrite/Models/ColumnUrl.cs(1 hunks)Appwrite/Models/Continent.cs(1 hunks)Appwrite/Models/ContinentList.cs(2 hunks)Appwrite/Models/Country.cs(1 hunks)Appwrite/Models/CountryList.cs(2 hunks)Appwrite/Models/Currency.cs(1 hunks)Appwrite/Models/CurrencyList.cs(2 hunks)Appwrite/Models/Database.cs(1 hunks)Appwrite/Models/DatabaseList.cs(2 hunks)Appwrite/Models/Deployment.cs(1 hunks)Appwrite/Models/DeploymentList.cs(2 hunks)Appwrite/Models/Document.cs(2 hunks)Appwrite/Models/DocumentList.cs(2 hunks)Appwrite/Models/Execution.cs(2 hunks)Appwrite/Models/ExecutionList.cs(2 hunks)Appwrite/Models/File.cs(2 hunks)Appwrite/Models/FileList.cs(2 hunks)Appwrite/Models/Framework.cs(2 hunks)Appwrite/Models/FrameworkAdapter.cs(1 hunks)Appwrite/Models/FrameworkList.cs(2 hunks)Appwrite/Models/Function.cs(3 hunks)Appwrite/Models/FunctionList.cs(2 hunks)Appwrite/Models/Headers.cs(1 hunks)Appwrite/Models/HealthAntivirus.cs(1 hunks)Appwrite/Models/HealthCertificate.cs(1 hunks)Appwrite/Models/HealthQueue.cs(1 hunks)Appwrite/Models/HealthStatus.cs(1 hunks)Appwrite/Models/HealthTime.cs(1 hunks)Appwrite/Models/Identity.cs(1 hunks)Appwrite/Models/IdentityList.cs(2 hunks)Appwrite/Models/Index.cs(2 hunks)Appwrite/Models/IndexList.cs(2 hunks)Appwrite/Models/JWT.cs(1 hunks)Appwrite/Models/Language.cs(1 hunks)Appwrite/Models/LanguageList.cs(2 hunks)Appwrite/Models/Locale.cs(1 hunks)Appwrite/Models/LocaleCode.cs(1 hunks)Appwrite/Models/LocaleCodeList.cs(2 hunks)Appwrite/Models/Log.cs(1 hunks)Appwrite/Models/LogList.cs(2 hunks)Appwrite/Models/Membership.cs(2 hunks)Appwrite/Models/MembershipList.cs(2 hunks)Appwrite/Models/Message.cs(2 hunks)Appwrite/Models/MessageList.cs(2 hunks)Appwrite/Models/MfaChallenge.cs(1 hunks)Appwrite/Models/MfaFactors.cs(1 hunks)Appwrite/Models/MfaRecoveryCodes.cs(2 hunks)Appwrite/Models/MfaType.cs(1 hunks)Appwrite/Models/Phone.cs(1 hunks)Appwrite/Models/PhoneList.cs(2 hunks)Appwrite/Models/Preferences.cs(1 hunks)Appwrite/Models/Provider.cs(1 hunks)Appwrite/Models/ProviderList.cs(2 hunks)Appwrite/Models/ResourceToken.cs(1 hunks)Appwrite/Models/ResourceTokenList.cs(2 hunks)Appwrite/Models/Row.cs(2 hunks)Appwrite/Models/RowList.cs(2 hunks)Appwrite/Models/Runtime.cs(2 hunks)Appwrite/Models/RuntimeList.cs(2 hunks)Appwrite/Models/Session.cs(2 hunks)Appwrite/Models/SessionList.cs(2 hunks)Appwrite/Models/Site.cs(2 hunks)Appwrite/Models/SiteList.cs(2 hunks)Appwrite/Models/Specification.cs(1 hunks)Appwrite/Models/SpecificationList.cs(2 hunks)Appwrite/Models/Subscriber.cs(1 hunks)
⛔ Files not processed due to max files limit (16)
- Appwrite/Models/SubscriberList.cs
 - Appwrite/Models/Table.cs
 - Appwrite/Models/TableList.cs
 - Appwrite/Models/Target.cs
 - Appwrite/Models/TargetList.cs
 - Appwrite/Models/Team.cs
 - Appwrite/Models/TeamList.cs
 - Appwrite/Models/Token.cs
 - Appwrite/Models/Topic.cs
 - Appwrite/Models/TopicList.cs
 - Appwrite/Models/Transaction.cs
 - Appwrite/Models/TransactionList.cs
 - Appwrite/Models/User.cs
 - Appwrite/Models/UserList.cs
 - Appwrite/Models/Variable.cs
 - Appwrite/Models/VariableList.cs
 
✅ Files skipped from review due to trivial changes (38)
- Appwrite/Models/AlgoScrypt.cs
 - Appwrite/Models/ColumnString.cs
 - Appwrite/Models/AttributeString.cs
 - Appwrite/Models/AlgoArgon2.cs
 - Appwrite/Models/Currency.cs
 - Appwrite/Models/Log.cs
 - Appwrite/Models/Identity.cs
 - Appwrite/Models/AlgoPhpass.cs
 - Appwrite/Models/Deployment.cs
 - Appwrite/Models/JWT.cs
 - Appwrite/Models/AttributeInteger.cs
 - Appwrite/Models/Locale.cs
 - Appwrite/Models/AttributeIp.cs
 - Appwrite/Models/ResourceToken.cs
 - Appwrite/Models/Subscriber.cs
 - Appwrite/Models/Continent.cs
 - Appwrite/Models/ColumnRelationship.cs
 - Appwrite/Models/AlgoScryptModified.cs
 - Appwrite/Models/ColumnUrl.cs
 - Appwrite/Models/Headers.cs
 - Appwrite/Models/MfaType.cs
 - Appwrite/Models/Country.cs
 - Appwrite/Models/Provider.cs
 - Appwrite/Models/HealthStatus.cs
 - Appwrite/Models/Preferences.cs
 - Appwrite/Models/AttributeEmail.cs
 - Appwrite/Models/HealthTime.cs
 - Appwrite/Models/Framework.cs
 - Appwrite/Models/LocaleCode.cs
 - Appwrite/Models/HealthQueue.cs
 - Appwrite/Models/ColumnBoolean.cs
 - Appwrite/Models/MfaFactors.cs
 - Appwrite/Models/ColumnFloat.cs
 - Appwrite/Models/Database.cs
 - Appwrite/Models/HealthCertificate.cs
 - Appwrite/Models/ColumnDatetime.cs
 - Appwrite/Models/MfaChallenge.cs
 - Appwrite/Models/HealthAntivirus.cs
 
🧰 Additional context used
🧬 Code graph analysis (69)
Appwrite/Models/FrameworkAdapter.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Site.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Variable.cs (4)
Dictionary(69-79)Variable(12-80)Variable(38-56)Variable(58-67)
Appwrite/Models/AttributeFloat.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ColumnIp.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/LocaleCodeList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/LocaleCode.cs (3)
LocaleCode(12-38)LocaleCode(20-26)LocaleCode(28-31)
Appwrite/Models/ColumnList.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Collection.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Index.cs (4)
Dictionary(81-93)Index(12-94)Index(44-66)Index(68-79)
Appwrite/Models/ColumnEmail.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Runtime.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeList.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ResourceTokenList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/ResourceToken.cs (4)
Dictionary(63-72)ResourceToken(12-73)ResourceToken(35-51)ResourceToken(53-61)
Appwrite/Models/SessionList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Session.cs (3)
Session(12-227)Session(101-161)Session(163-193)
Appwrite/Models/MfaRecoveryCodes.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ContinentList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Continent.cs (3)
Continent(12-38)Continent(20-26)Continent(28-31)
Appwrite/Models/ColumnIndexList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/ColumnIndex.cs (4)
Dictionary(81-93)ColumnIndex(12-94)ColumnIndex(44-66)ColumnIndex(68-79)
Appwrite/Models/Index.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/BucketList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Bucket.cs (4)
Dictionary(93-107)Bucket(12-108)Bucket(50-76)Bucket(78-91)
Appwrite/Models/IdentityList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Identity.cs (3)
Identity(12-94)Identity(44-66)Identity(68-79)
Appwrite/Models/SiteList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Site.cs (4)
Dictionary(195-226)Site(12-227)Site(101-161)Site(163-193)
Appwrite/Models/Phone.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Row.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AlgoSha.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/RuntimeList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Runtime.cs (3)
Runtime(12-80)Runtime(38-56)Runtime(58-67)
Appwrite/Models/CountryList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Country.cs (3)
Country(12-38)Country(20-26)Country(28-31)
Appwrite/Models/LogList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Log.cs (3)
Log(12-171)Log(77-121)Log(123-145)
Appwrite/Models/Message.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/FrameworkList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Framework.cs (4)
Dictionary(51-58)Framework(12-59)Framework(29-41)Framework(43-49)
Appwrite/Models/ColumnPoint.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Language.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/File.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/SpecificationList.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/IndexList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Index.cs (3)
Index(12-94)Index(44-66)Index(68-79)
Appwrite/Models/AlgoBcrypt.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeLine.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/MessageList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Message.cs (3)
Message(12-115)Message(53-81)Message(83-97)
Appwrite/Models/AttributeEnum.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ColumnPolygon.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeUrl.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Function.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Variable.cs (3)
Variable(12-80)Variable(38-56)Variable(58-67)
Appwrite/Models/ColumnEnum.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ProviderList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Provider.cs (3)
Provider(12-87)Provider(41-61)Provider(63-73)
Appwrite/Models/MembershipList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Membership.cs (3)
Membership(12-115)Membership(53-81)Membership(83-97)
Appwrite/Models/AttributePolygon.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/CollectionList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Collection.cs (4)
Dictionary(81-93)Collection(12-94)Collection(44-66)Collection(68-79)
Appwrite/Models/AttributePoint.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeDatetime.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeBoolean.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ColumnIndex.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ColumnLine.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/AttributeRelationship.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/DeploymentList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Deployment.cs (3)
Deployment(12-213)Deployment(95-151)Deployment(153-181)
Appwrite/Models/AlgoMd5.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Document.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Membership.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Execution.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Headers.cs (3)
Headers(12-38)Headers(20-26)Headers(28-31)
Appwrite/Models/LanguageList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Language.cs (3)
Language(12-45)Language(23-31)Language(33-37)
Appwrite/Models/CurrencyList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Currency.cs (3)
Currency(12-73)Currency(35-51)Currency(53-61)
Appwrite/Models/Specification.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/FunctionList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Function.cs (3)
Function(12-220)Function(98-156)Function(158-187)
Appwrite/Models/Session.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/Bucket.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
Appwrite/Models/ExecutionList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Execution.cs (3)
Execution(12-150)Execution(68-106)Execution(108-127)
Appwrite/Models/DatabaseList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Database.cs (3)
Database(12-66)Database(32-46)Database(48-55)
Appwrite/Models/RowList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Row.cs (4)
Dictionary(68-78)Row(12-82)Row(37-55)Row(57-66)
Appwrite/Extensions/Extensions.cs (3)
Appwrite/Models/Document.cs (1)
T(80-81)Appwrite/Models/DocumentList.cs (1)
T(39-40)Appwrite/Models/Preferences.cs (1)
T(31-32)
Appwrite/Models/FileList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/File.cs (3)
File(12-101)File(47-71)File(73-85)
Appwrite/Models/PhoneList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Phone.cs (3)
Phone(12-45)Phone(23-31)Phone(33-37)
Appwrite/Models/DocumentList.cs (2)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)Appwrite/Models/Document.cs (3)
Document(12-82)Document(37-55)Document(57-66)
Appwrite/Models/ColumnInteger.cs (1)
Appwrite/Extensions/Extensions.cs (1)
Extensions(9-639)
🔇 Additional comments (46)
Appwrite/Models/ColumnIp.cs (1)
8-8: LGTM: import aligns with project-wide Extensions usageConsistent with other models; no concerns.
Appwrite/Models/ColumnPolygon.cs (1)
8-8: LGTM: import required for ConvertToListMatches the new deserialization pattern.
Appwrite/Models/ColumnEmail.cs (1)
8-8: LGTM: added Extensions importConsistent with the codebase changes.
Appwrite/Models/AttributeFloat.cs (1)
8-8: LGTM: import additionNo behavioral change; consistent with repo-wide updates.
Appwrite/Models/Phone.cs (1)
8-8: Import addition looks good.
Bringing inAppwrite.Extensionskeeps this model ready for the shared conversion helpers; nothing further needed here.Appwrite/Models/AttributeBoolean.cs (1)
8-8: Consistent namespace import.
ImportingAppwrite.Extensionsaligns this model with the shared helpers used elsewhere; no issues.Appwrite/Models/Language.cs (1)
8-8: Namespace update looks fine.
IncludingAppwrite.Extensionskeeps the file consistent with the rest of the models using the shared helpers.Appwrite/Models/FrameworkAdapter.cs (1)
8-8: Import aligns with shared helpers.
This keeps the adapter ready for the new extension utilities; no concerns.Appwrite/Models/AttributeRelationship.cs (1)
8-8: Looks consistent with the rest of the update.
AddingAppwrite.Extensionsmaintains parity with other models adopting the shared conversion helpers.Appwrite/Models/MfaRecoveryCodes.cs (1)
8-8: LGTM! Consistent refactoring to use the extension method.The addition of the
Appwrite.Extensionsnamespace and the use ofConvertToList<string>()correctly standardizes list deserialization across the codebase. SinceRecoveryCodesis non-nullable, there are no null-handling concerns.Also applies to: 24-24
Appwrite/Models/LocaleCodeList.cs (1)
8-8: LGTM! Consistent refactoring pattern.The use of
ConvertToList<Dictionary<string, object>>()followed bySelectandToList()correctly standardizes the deserialization pattern across the codebase. SinceLocaleCodesis non-nullable, there are no null-handling concerns.Also applies to: 30-30
Appwrite/Models/CountryList.cs (1)
8-8: LGTM! Consistent refactoring pattern.The use of
ConvertToList<Dictionary<string, object>>()followed bySelectandToList()correctly standardizes the deserialization pattern. SinceCountriesis non-nullable, there are no null-handling concerns.Also applies to: 30-30
Appwrite/Models/FrameworkList.cs (1)
8-8: LGTM! Consistent refactoring pattern.The use of
ConvertToList<Dictionary<string, object>>()followed bySelectandToList()correctly standardizes the deserialization pattern. SinceFrameworksis non-nullable, there are no null-handling concerns.Also applies to: 30-30
Appwrite/Models/Runtime.cs (1)
66-67: LGTM, assuming ConvertToList fix is applied
supportspath is correct after centralization. Ensure the ConvertToList() change to use Client.SerializerOptions is in place.Appwrite/Models/ProviderList.cs (1)
30-31: LGTMCentralized providers conversion is clean. Ensure the ConvertToList() serializer-options fix is applied globally.
Appwrite/Models/LogList.cs (1)
8-8: LGTM! Clean refactoring to use the centralized extension method.The addition of the
Appwrite.Extensionsnamespace and the use ofConvertToList<T>()simplifies the deserialization logic by removing conditional branching. This pattern is consistent with the broader refactor across the codebase.Also applies to: 30-30
Appwrite/Models/IdentityList.cs (1)
8-8: LGTM! Refactor standardizes list deserialization.The addition of
using Appwrite.Extensionsand the use ofConvertToList<Dictionary<string, object>>()aligns with the project-wide refactor to centralize list conversion logic. This simplifies the deserialization by replacing conditional type checks with a uniform conversion path.Also applies to: 30-30
Appwrite/Models/LanguageList.cs (1)
8-8: LGTM! Consistent with the standardization effort.The refactor follows the same pattern as other models, using
ConvertToList<Dictionary<string, object>>()to simplify list deserialization.Also applies to: 30-30
Appwrite/Models/MessageList.cs (1)
8-8: LGTM! Refactor aligns with project standards.Consistent with other model files in this PR, the change simplifies list extraction using
ConvertToList<T>().Also applies to: 30-30
Appwrite/Models/Document.cs (1)
8-8: LGTM! Simplifies permissions deserialization.The refactor uses
ConvertToList<string>()to handle the$permissionsfield, removing conditional type checks and aligning with the uniform conversion pattern used across the SDK.Also applies to: 64-64
Appwrite/Models/Membership.cs (1)
8-8: LGTM! Consistent refactor for roles list.The use of
ConvertToList<string>()for therolesfield standardizes list deserialization and removes conditional branches.Also applies to: 96-96
Appwrite/Models/Bucket.cs (1)
8-8: LGTM! Consistent refactor for multiple list fields.Both
$permissionsandallowedFileExtensionsnow useConvertToList<string>(), simplifying deserialization logic and aligning with the project-wide standardization effort.Also applies to: 82-82, 87-87
Appwrite/Models/Index.cs (1)
8-8: LGTM! Consistent refactor for attributes and lengths.The use of
ConvertToList<string>()andConvertToList<long>()forattributesandlengthsaligns with the standardization effort.Also applies to: 76-77
Appwrite/Models/Site.cs (1)
8-8: LGTM: Deserialization standardized with ConvertToList extension.The addition of
using Appwrite.Extensionsand the refactored deserialization logic for thevarsfield usingConvertToList<Dictionary<string, object>>()improves code consistency across the SDK. This change aligns with the broader refactor to unify list extraction logic.Also applies to: 179-179
Appwrite/Models/ColumnEnum.cs (1)
8-8: LGTM: Consistent refactor for list deserialization.The updated deserialization of the
elementsfield usingConvertToList<string>()follows the established pattern across the SDK, improving maintainability.Also applies to: 82-82
Appwrite/Models/File.cs (1)
8-8: LGTM: Permissions deserialization improved.The refactored deserialization of the
$permissionsfield usingConvertToList<string>()is consistent with the SDK-wide refactor and maintains type safety.Also applies to: 78-78
Appwrite/Models/SpecificationList.cs (1)
8-8: LGTM: List deserialization standardized.The updated deserialization path for
specificationsusingConvertToList<Dictionary<string, object>>()followed by mapping each item toSpecificationis consistent with the SDK-wide refactor.Also applies to: 30-30
Appwrite/Models/CollectionList.cs (1)
8-8: LGTM: Unified deserialization approach.The collections field now uses the standardized
ConvertToList<Dictionary<string, object>>()approach, consistent with other list-based model files in this refactor.Also applies to: 30-30
Appwrite/Models/BucketList.cs (1)
8-8: LGTM: Bucket list deserialization improved.The refactored deserialization of the
bucketsfield usingConvertToList<Dictionary<string, object>>()is consistent with the SDK-wide standardization effort.Also applies to: 30-30
Appwrite/Models/DocumentList.cs (1)
8-8: LGTM: Document list deserialization standardized.The updated deserialization logic for the
documentsfield usingConvertToList<Dictionary<string, object>>()aligns with the consistent pattern established across all model files.Also applies to: 30-30
Appwrite/Models/AttributeEnum.cs (1)
8-8: LGTM: Elements deserialization standardized.The refactored deserialization of the
elementsfield usingConvertToList<string>()is consistent with the SDK-wide effort to unify list extraction logic.Also applies to: 82-82
Appwrite/Models/Collection.cs (1)
8-8: LGTM! Consistent refactor to ConvertToList pattern.The addition of the
Appwrite.Extensionsusing directive and the refactoring of list field deserialization (permissions, attributes, indexes) to use theConvertToList<T>()extension method improves code consistency and maintainability across the SDK.Also applies to: 72-72, 77-78
Appwrite/Models/SessionList.cs (1)
8-8: LGTM! Uniform list deserialization pattern applied.The refactor to use
ConvertToList<Dictionary<string, object>>()for the sessions field aligns with the SDK-wide consolidation of list handling logic.Also applies to: 30-30
Appwrite/Models/IndexList.cs (1)
8-8: LGTM! Consistent application of ConvertToList refactor.The indexes field now uses the standardized
ConvertToList<T>()extension, improving code uniformity across model deserialization.Also applies to: 30-30
Appwrite/Models/AttributeList.cs (1)
8-8: LGTM! Clean refactor to extension-based list conversion.The direct use of
ConvertToList<object>()for the attributes field simplifies the deserialization logic while maintaining consistency with the broader refactoring effort.Also applies to: 30-30
Appwrite/Models/MembershipList.cs (1)
8-8: LGTM! Refactor aligns with SDK-wide pattern.The memberships field now leverages the
ConvertToList<T>()extension, consistent with similar changes across other model classes.Also applies to: 30-30
Appwrite/Models/Session.cs (1)
8-8: LGTM! Factors field properly updated.The refactor to use
ConvertToList<string>()for the factors field maintains consistency with the SDK-wide list handling improvements.Also applies to: 190-190
Appwrite/Models/ColumnIndexList.cs (1)
8-8: LGTM! Consistent refactor applied.The indexes field now uses the standardized
ConvertToList<T>()extension, aligning with the uniform deserialization pattern established across the SDK.Also applies to: 30-30
Appwrite/Models/FileList.cs (1)
8-8: LGTM! Refactor completes the unified list handling pattern.The files field now uses
ConvertToList<T>(), completing the SDK-wide consolidation of list deserialization logic. This refactor improves maintainability by centralizing list conversion handling in a single, reusable extension method.Also applies to: 30-30
Appwrite/Models/FunctionList.cs (1)
8-8: LGTM! Consistent refactoring to use centralized list conversion.The addition of the
Appwrite.Extensionsnamespace and the use ofConvertToList<T>()aligns with the repository-wide refactoring to standardize list deserialization. The logic remains equivalent while improving maintainability.Also applies to: 30-30
Appwrite/Models/SiteList.cs (1)
8-8: LGTM! Consistent with the project-wide refactoring pattern.The changes follow the same pattern applied across multiple model files, using the
ConvertToList<T>()extension to standardize list deserialization.Also applies to: 30-30
Appwrite/Models/ExecutionList.cs (1)
8-8: LGTM! Refactoring aligns with project standards.The use of
ConvertToList<T>()is consistent with similar changes across the codebase, consolidating list deserialization logic into the extension method.Also applies to: 30-30
Appwrite/Models/RuntimeList.cs (1)
8-8: LGTM! Follows the established refactoring pattern.The changes are consistent with the broader SDK update to standardize list deserialization using the
ConvertToList<T>()extension.Also applies to: 30-30
Appwrite/Models/ColumnIndex.cs (1)
76-77: LGTM! Consistent refactoring for columns and lengths.The use of
ConvertToList<T>()appropriately handles the list conversion forcolumnsandlengthsproperties.Appwrite/Models/Function.cs (1)
8-8: LGTM! Comprehensive refactoring of list deserialization.The changes consistently apply
ConvertToList<T>()across multiple list properties (execute,scopes,vars,events). The nested mapping forvarsviaVariable.Fromis handled correctly.Also applies to: 162-175
Appwrite/Models/Execution.cs (1)
8-8: LGTM! Refactoring streamlines list deserialization.The changes apply
ConvertToList<T>()consistently forpermissions,requestHeaders, andresponseHeaders. The nested mapping throughHeaders.Fromfor header lists is correctly implemented.Also applies to: 112-122
| public static List<T> ConvertToList<T>(this object value) | ||
| { | ||
| return value switch | ||
| { | ||
| JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."), | ||
| object[] objArray => objArray.Cast<T>().ToList(), | ||
| List<T> list => list, | ||
| IEnumerable<T> enumerable => enumerable.ToList(), | ||
| _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>") | ||
| }; | ||
| } | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix null handling and use Client.SerializerOptions in ConvertToList
- Null input currently triggers a NullReferenceException via value.GetType().
 - Deserialize with Client.SerializerOptions for consistency.
 
Apply:
-        public static List<T> ConvertToList<T>(this object value)
-        {
-            return value switch
-            {
-                JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),
-                object[] objArray => objArray.Cast<T>().ToList(),
-                List<T> list => list,
-                IEnumerable<T> enumerable => enumerable.ToList(),
-                _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>")
-            };
-        }
+        public static List<T> ConvertToList<T>(this object value)
+        {
+            return value switch
+            {
+                null => throw new InvalidCastException($"Cannot convert null to List<{typeof(T)}>"),
+                JsonElement jsonElement => jsonElement.Deserialize<List<T>>(Client.SerializerOptions) ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),
+                object[] objArray => objArray.Cast<T>().ToList(),
+                List<T> list => list,
+                IEnumerable<T> enumerable => enumerable.ToList(),
+                _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>")
+            };
+        }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| public static List<T> ConvertToList<T>(this object value) | |
| { | |
| return value switch | |
| { | |
| JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."), | |
| object[] objArray => objArray.Cast<T>().ToList(), | |
| List<T> list => list, | |
| IEnumerable<T> enumerable => enumerable.ToList(), | |
| _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>") | |
| }; | |
| } | |
| public static List<T> ConvertToList<T>(this object value) | |
| { | |
| return value switch | |
| { | |
| null => throw new InvalidCastException($"Cannot convert null to List<{typeof(T)}>"), | |
| JsonElement jsonElement => jsonElement.Deserialize<List<T>>(Client.SerializerOptions) | |
| ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>"), | |
| object[] objArray => objArray.Cast<T>().ToList(), | |
| List<T> list => list, | |
| IEnumerable<T> enumerable => enumerable.ToList(), | |
| _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>") | |
| }; | |
| } | 
🤖 Prompt for AI Agents
In Appwrite/Extensions/Extensions.cs around lines 16 to 26, add a null check at
the top to avoid calling value.GetType() on null (throw an InvalidCastException
with a clear message like "Cannot convert null to List<T>"), and when handling
JsonElement use jsonElement.Deserialize<List<T>>(Client.SerializerOptions)
instead of the parameterless overload; keep the other branches the same and
ensure all thrown InvalidCastException messages remain descriptive.
| createdAt: map["$createdAt"].ToString(), | ||
| updatedAt: map["$updatedAt"].ToString(), | ||
| xdefault: map["default"] is JsonElement jsonArrayProp9 ? jsonArrayProp9.Deserialize<List<object>>()! : (List<object>)map["default"] | ||
| xdefault: map["default"].ConvertToList<object>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null handling missing for nullable field.
The Default property is nullable (List<object>?), but ConvertToList<object>() does not handle null input. If map["default"] is null, this will throw a NullReferenceException.
Apply this diff to add null-coalescing:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: map["default"] as object == null ? null : map["default"].ConvertToList<object>()Alternatively, update the ConvertToList<T> extension method in Appwrite/Extensions/Extensions.cs to handle null input (see comment on AttributePoint.cs for details).
🤖 Prompt for AI Agents
In Appwrite/Models/AttributeLine.cs around line 72, the mapping for xdefault
uses map["default"].ConvertToList<object>() which will throw if map["default"]
is null; change it to use a null-safe call so Default is assigned null when the
source is null (e.g., use map["default"]?.ConvertToList<object>() or conditional
null coalescing to return null), or alternatively update ConvertToList<T> in
Appwrite/Extensions/Extensions.cs to accept null input and return null so
existing calls remain safe.
| createdAt: map["$createdAt"].ToString(), | ||
| updatedAt: map["$updatedAt"].ToString(), | ||
| xdefault: map["default"] is JsonElement jsonArrayProp9 ? jsonArrayProp9.Deserialize<List<object>>()! : (List<object>)map["default"] | ||
| xdefault: map["default"].ConvertToList<object>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null handling missing for nullable field.
The Default property is nullable (List<object>?), but ConvertToList<object>() does not handle null input. If map["default"] is null, this will throw a NullReferenceException when the extension method attempts to call value.GetType() in the default switch case.
Apply this diff to add null-coalescing:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: map["default"] as object == null ? null : map["default"].ConvertToList<object>()Alternatively, update the ConvertToList<T> extension method to handle null input:
 public static List<T> ConvertToList<T>(this object value)
 {
     return value switch
     {
+        null => null,
         JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),
         object[] objArray => objArray.Cast<T>().ToList(),
         List<T> list => list,
         IEnumerable<T> enumerable => enumerable.ToList(),
         _ => throw new InvalidCastException($"Cannot convert {value.GetType()} to List<{typeof(T)}>")
     };
 }Note: The second approach would require changing the return type to List<T>? if the return can be null.
🤖 Prompt for AI Agents
In Appwrite/Models/AttributePoint.cs around line 72, the Nullable Default
property is assigned using map["default"].ConvertToList<object>() which will
throw if map["default"] is null; update the assignment to handle null (e.g.,
xdefault: map["default"] == null ? null :
map["default"].ConvertToList<object>()) or alternatively change the
ConvertToList<T> extension to accept a nullable input and return List<T>? so
null inputs produce null instead of throwing — implement one of these fixes and
update the property's usage/type accordingly.
| xdefault: map["default"].ConvertToList<object>() | ||
| ); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Blocker: Optional default must be null-safe; current code throws on missing/null (incl. JsonElement.Null)
Handle absence/null safely before ConvertToList to preserve List<object>? semantics:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: (map.TryGetValue("default", out var d) && d is not JsonElement { ValueKind: JsonValueKind.Null } && d != null)
+                ? d.ConvertToList<object>()
+                : nullAlso ensure ConvertToList() uses Client.SerializerOptions as noted earlier, or inner values may be JsonElement and break downstream casts.
🏁 Script executed:
#!/bin/bash
sed -n '1,200p' Appwrite/Models/AttributePolygon.csLength of output: 2640
🏁 Script executed:
#!/bin/bash
rg -n "ConvertToList" -g "Appwrite/Extensions/*.cs"Length of output: 102
🏁 Script executed:
#!/bin/bash
sed -n '1,200p' Appwrite/Extensions/Extensions.csLength of output: 9058
Guard missing for nullable default field in From constructor
Prevent crashes when "default" is absent or null by wrapping its access:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: map.TryGetValue("default", out var d) && d is not JsonElement { ValueKind: JsonValueKind.Null } && d != null
+                ? d.ConvertToList<object>()
+                : nullOptional: update ConvertToList<T> to pass Client.SerializerOptions into JsonElement.Deserialize<> to ensure consistent deserialization.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| xdefault: map["default"].ConvertToList<object>() | |
| ); | |
| // … other properties … | |
| xdefault: map.TryGetValue("default", out var d) | |
| && d is not JsonElement { ValueKind: JsonValueKind.Null } | |
| && d != null | |
| ? d.ConvertToList<object>() | |
| : null | |
| ); | 
🤖 Prompt for AI Agents
In Appwrite/Models/AttributePolygon.cs around lines 72-73, the From constructor
unguardedly accesses map["default"] and calls ConvertToList<object>(), which
will throw if "default" is missing or null; update the constructor to check for
the key and that its value is not null (e.g., conditional access or TryGetValue)
and only call ConvertToList<object>() when present, otherwise pass null or an
empty list to the xdefault parameter; optionally, update ConvertToList<T> to
forward Client.SerializerOptions into JsonElement.Deserialize<T> so
deserialization respects the shared serializer options.
| orders: map["orders"] is JsonElement jsonArrayProp10 ? jsonArrayProp10.Deserialize<List<string>>()! : (List<string>)map["orders"] | ||
| columns: map["columns"].ConvertToList<string>(), | ||
| lengths: map["lengths"].ConvertToList<long>(), | ||
| orders: map["orders"].ConvertToList<string>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify null handling for the nullable Orders property.
The Orders property is declared as List<string>? (nullable), but ConvertToList<string>() returns a non-nullable List<string> and will throw InvalidCastException if map["orders"] is null. Ensure that map["orders"] is never null, or add null-coalescing logic if null is a valid state.
🏁 Script executed:
#!/bin/bash
# Description: Search for how orders is populated in the codebase to verify null handling
# Search for assignments to "orders" key in dictionaries
rg -n -C 3 '\["orders"\]' --type cs
# Search for ColumnIndex instantiation patterns
ast-grep --pattern $'new ColumnIndex(
  $$$
)'Length of output: 2091
🏁 Script executed:
#!/bin/bash
# Inspect ColumnIndex class and Orders property
rg -n 'class ColumnIndex' -n5 Appwrite/Models/ColumnIndex.cs
rg -n 'public .*Orders' -n3 Appwrite/Models/ColumnIndex.cs
# Locate ConvertToList definition
rg -n 'ConvertToList<' -n5Length of output: 1214
🏁 Script executed:
#!/bin/bash
# Inspect ColumnIndex class context and Orders property
rg -n 'class ColumnIndex' -C5 Appwrite/Models/ColumnIndex.cs
rg -n 'public .*Orders' -C3 Appwrite/Models/ColumnIndex.cs
# Locate ConvertToList<T> definition across the repo
rg -n 'ConvertToList<.*>' -C3 .Length of output: 45859
🏁 Script executed:
#!/bin/bash
# Extract ConvertToList<T> implementation to inspect null handling
sed -n '1,200p' Appwrite/Extensions/Extensions.cs | sed -n '1,50p'Length of output: 1746
Guard map["orders"] against null before calling ConvertToList (ColumnIndex.cs:78)
ConvertToList doesn’t handle null and will throw if map["orders"] is missing or null. Wrap it with a null check, for example:
orders: map.TryGetValue("orders", out var o) && o != null
    ? o.ConvertToList<string>()
    : null🤖 Prompt for AI Agents
In Appwrite/Models/ColumnIndex.cs around line 78, the code calls
map["orders"].ConvertToList<string>() without guarding for a missing or null key
which will throw; change it to first TryGetValue("orders", out var o) and if o
is non-null call o.ConvertToList<string>(), otherwise assign null (i.e., only
call ConvertToList when the value exists and is not null).
| createdAt: map["$createdAt"].ToString(), | ||
| updatedAt: map["$updatedAt"].ToString(), | ||
| xdefault: map["default"] is JsonElement jsonArrayProp9 ? jsonArrayProp9.Deserialize<List<object>>()! : (List<object>)map["default"] | ||
| xdefault: map["default"].ConvertToList<object>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null handling missing for nullable field.
The Default property is nullable (List<object>?), but ConvertToList<object>() does not handle null input. If map["default"] is null, this will throw a NullReferenceException.
Apply this diff to add null-coalescing:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: map["default"] as object == null ? null : map["default"].ConvertToList<object>()Alternatively, update the ConvertToList<T> extension method in Appwrite/Extensions/Extensions.cs to handle null input (see comment on AttributePoint.cs for details).
🤖 Prompt for AI Agents
In Appwrite/Models/ColumnPoint.cs around line 72, the assignment xdefault:
map["default"].ConvertToList<object>() can throw if map["default"] is null;
change it to use null-safe handling (e.g. xdefault:
map["default"]?.ConvertToList<object>() or map["default"] == null ? null :
map["default"].ConvertToList<object>()) so the List<object>? stays null when
input is null, or alternatively update the ConvertToList<T> extension in
Appwrite/Extensions/Extensions.cs to return null when given a null input so
callers don’t need to null-check.
| createdAt: map["$createdAt"].ToString(), | ||
| updatedAt: map["$updatedAt"].ToString(), | ||
| xdefault: map["default"] is JsonElement jsonArrayProp9 ? jsonArrayProp9.Deserialize<List<object>>()! : (List<object>)map["default"] | ||
| xdefault: map["default"].ConvertToList<object>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Null-safety for optional 'default' value
'default' is nullable; calling ConvertToList on a missing/null value will throw. Guard it.
Apply:
-            xdefault: map["default"].ConvertToList<object>()
+            xdefault: map.TryGetValue("default", out var defaultObj) && defaultObj != null
+                ? defaultObj.ConvertToList<object>()
+                : null📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| xdefault: map["default"].ConvertToList<object>() | |
| xdefault: map.TryGetValue("default", out var defaultObj) && defaultObj != null | |
| ? defaultObj.ConvertToList<object>() | |
| : null | 
🤖 Prompt for AI Agents
In Appwrite/Models/ColumnPolygon.cs around line 72, the code calls
map["default"].ConvertToList<object>() unguarded; since 'default' is optional
and may be null or missing this will throw. Fix by checking whether map contains
the "default" key and that map["default"] is not null before calling
ConvertToList (or use a null-conditional/ternary to assign a null/empty list
when absent). Ensure the resulting property is set to the converted list only
when the value exists, otherwise set it to null (or an appropriate default).
| currencies: map["currencies"].ConvertToList<Dictionary<string, object>>().Select(it => Currency.From(map: it)).ToList() | ||
| ); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Blocker: ConvertToList() uses default JsonSerializer options → nested values become JsonElement and break Currency.From casts
With JsonElement.Deserialize<List>() default options, inner dictionary values are JsonElement. Currency.From uses Convert.ToInt64/ToDouble and direct casts, which will throw on JsonElement.
Fix ConvertToList to use Client.SerializerOptions:
-        JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),
+        JsonElement jsonElement => jsonElement.Deserialize<List<T>>(Client.SerializerOptions) ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),Inspecting ConvertToList<T> implementation to verify JSON serializer options usage.
🏁 Script executed:
rg -n "ConvertToList" -C3 -g "*.cs"Length of output: 44338
Printing ConvertToList<T> implementation for verification.
🏁 Script executed:
sed -n '1,200p' Appwrite/Extensions/Extensions.csLength of output: 9058
Printing Currency.From implementation to verify casts.
🏁 Script executed:
rg -n "public static Currency From" -C5 -g "Appwrite/Models/Currency.cs"Length of output: 800
Critical: Pass Client.SerializerOptions when deserializing in ConvertToList
ConvertToList currently calls jsonElement.Deserialize<List<T>>() with default options, so nested values remain JsonElement and will break Convert.ToInt64/Convert.ToDouble in Currency.From. Update the JsonElement case in Appwrite/Extensions/Extensions.cs:
-        JsonElement jsonElement => jsonElement.Deserialize<List<T>>() ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),  
+        JsonElement jsonElement => jsonElement.Deserialize<List<T>>(Client.SerializerOptions) ?? throw new InvalidCastException($"Cannot deserialize {jsonElement} to List<{typeof(T)}>."),  Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
Appwrite/Extensions/Extensions.cs (JsonElement ConvertToList<T> case): the
ConvertToList<T> implementation deserializes JsonElement using default options
so nested JsonElement values remain and later conversions (e.g., in
Currency.From) fail; change the JsonElement branch to call
jsonElement.Deserialize<List<T>>() with the library's Client.SerializerOptions
(or the appropriate serializer options instance) so deserialization uses the
configured converters and produces proper typed values.
| orders: map["orders"] is JsonElement jsonArrayProp10 ? jsonArrayProp10.Deserialize<List<string>>()! : (List<string>)map["orders"] | ||
| attributes: map["attributes"].ConvertToList<string>(), | ||
| lengths: map["lengths"].ConvertToList<long>(), | ||
| orders: map["orders"].ConvertToList<string>() | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Verify null handling for nullable Orders property.
The Orders property is declared as nullable (List<string>? on line 42), but ConvertToList<string>() returns a non-nullable List<string>. According to the ConvertToList implementation, it throws an InvalidCastException when the input value doesn't match any of the handled patterns, including when the value is null.
If map["orders"] can be null, this will throw an exception rather than assigning null to the Orders property.
Verify whether map["orders"] can be null in practice by running the following script:
If orders can be null, apply this diff to handle it explicitly:
-            orders: map["orders"].ConvertToList<string>()
+            orders: map.TryGetValue("orders", out var ordersValue) && ordersValue != null 
+                ? ordersValue.ConvertToList<string>() 
+                : null🏁 Script executed:
#!/bin/bash
# Search for Index.From usages and Index construction patterns to understand if orders can be null
# Look for patterns where Index is constructed or From is called
rg -nP --type=cs -C5 'Index\.From|new Index\(' -g '!**/Models/Index.cs'
# Search for API responses or data structures that might set orders to null
rg -nP --type=cs 'orders.*null|null.*orders' -g '!**/Models/Index.cs'Length of output: 6768
🏁 Script executed:
#!/bin/bash
rg -n 'class Index' -n -C3 Appwrite/Models/Index.cs
sed -n '1,120p' Appwrite/Models/Index.csLength of output: 3018
Handle null orders in Index.From
When map["orders"] is null, ConvertToList<string>() will throw instead of yielding null. Change the From method to:
-            orders: map["orders"].ConvertToList<string>()
+            orders: map.TryGetValue("orders", out var ordersValue) && ordersValue != null
+                ? ordersValue.ConvertToList<string>()
+                : null📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| orders: map["orders"].ConvertToList<string>() | |
| orders: map.TryGetValue("orders", out var ordersValue) && ordersValue != null | |
| ? ordersValue.ConvertToList<string>() | |
| : null | 
🤖 Prompt for AI Agents
In Appwrite/Models/Index.cs around line 78, the current call
map["orders"].ConvertToList<string>() will throw when map["orders"] is null;
update the Index.From method to check for null (or key absence) before
converting and assign null when map["orders"] is null, otherwise call
ConvertToList<string>() — ensure you perform a null-safe lookup (e.g.,
map.ContainsKey("orders") and map["orders"] != null) and set orders accordingly.
| topics: map["topics"].ConvertToList<string>(), | ||
| users: map["users"].ConvertToList<string>(), | ||
| targets: map["targets"].ConvertToList<string>(), | ||
| scheduledAt: map.TryGetValue("scheduledAt", out var scheduledAt) ? scheduledAt?.ToString() : null, | ||
| deliveredAt: map.TryGetValue("deliveredAt", out var deliveredAt) ? deliveredAt?.ToString() : null, | ||
| deliveryErrors: map["deliveryErrors"] is JsonElement jsonArrayProp10 ? jsonArrayProp10.Deserialize<List<string>>()! : (List<string>)map["deliveryErrors"], | ||
| deliveryErrors: map["deliveryErrors"].ConvertToList<string>(), | ||
| deliveredTotal: Convert.ToInt64(map["deliveredTotal"]), | ||
| data: map["data"].ToString(), | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make list conversions null-safe and preserve Data type
- topics/users/targets: default to [] if missing/null.
 - deliveryErrors: return null if missing/null (property is nullable).
 - data: avoid ToString(); keep original object to prevent loss of structure.
 
Apply:
-            topics: map["topics"].ConvertToList<string>(),
-            users: map["users"].ConvertToList<string>(),
-            targets: map["targets"].ConvertToList<string>(),
+            topics: map.TryGetValue("topics", out var topicsObj) && topicsObj != null ? topicsObj.ConvertToList<string>() : new List<string>(),
+            users: map.TryGetValue("users", out var usersObj) && usersObj != null ? usersObj.ConvertToList<string>() : new List<string>(),
+            targets: map.TryGetValue("targets", out var targetsObj) && targetsObj != null ? targetsObj.ConvertToList<string>() : new List<string>(),
             scheduledAt: map.TryGetValue("scheduledAt", out var scheduledAt) ? scheduledAt?.ToString() : null,
             deliveredAt: map.TryGetValue("deliveredAt", out var deliveredAt) ? deliveredAt?.ToString() : null,
-            deliveryErrors: map["deliveryErrors"].ConvertToList<string>(),
+            deliveryErrors: map.TryGetValue("deliveryErrors", out var errorsObj) && errorsObj != null ? errorsObj.ConvertToList<string>() : null,
             deliveredTotal: Convert.ToInt64(map["deliveredTotal"]),
-            data: map["data"].ToString(),
+            data: map["data"],
             status: new MessageStatus(map["status"].ToString()!)🤖 Prompt for AI Agents
In Appwrite/Models/Message.cs around lines 88 to 95, make the list conversions
null-safe and preserve the original Data type: for topics, users and targets use
TryGetValue and default to an empty list when the key is missing or value is
null (e.g. map.TryGetValue("topics", out var t) ? t?.ConvertToList<string>() ??
new List<string>() : new List<string>()), for deliveryErrors return null when
the key is missing or value is null (use TryGetValue and if null then assign
null else call ConvertToList<string>()), and for data avoid ToString()—assign
the original map["data"] (or the value from TryGetValue) so the object structure
is preserved rather than converting to a string.
This PR contains updates to the .NET SDK for version 0.21.2.
Summary by CodeRabbit
Bug Fixes
Documentation
Chores