Skip to content

Conversation

@ChiragAgg5k
Copy link
Member

@ChiragAgg5k ChiragAgg5k commented Oct 13, 2025

This PR contains updates to the .NET SDK for version 0.21.2.

Summary by CodeRabbit

  • Bug Fixes

    • Improved array deserialization to correctly handle mixed/object arrays, reducing parsing errors.
  • Documentation

    • Updated guides and examples to reference version 0.21.2.
    • Added changelog entry for 0.21.2.
  • Chores

    • Bumped SDK/package version to 0.21.2.
    • Updated default request headers to reflect the new version.

@coderabbitai
Copy link

coderabbitai bot commented Oct 13, 2025

Walkthrough

Version bumped from 0.21.1 to 0.21.2 (Appwrite.csproj) and client default headers updated (user-agent, x-sdk-version). A new extension method ConvertToList<T>(this object) was added and imported across many model files; numerous From() implementations were changed to use ConvertToList<T>() instead of conditional JsonElement or IEnumerable branches. CHANGELOG and README updated for 0.21.2. No public/exported API signatures were changed.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly indicates that this pull request introduces a new feature by updating the .NET SDK to version 0.21.2, which matches the primary change in the changeset and is both concise and specific.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ChiragAgg5k ChiragAgg5k requested a review from Copilot October 13, 2025 09:29
Copy link

Copilot AI left a 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 including Object[], 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.

Copy link

@coderabbitai coderabbitai bot left a 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 list

If 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 the From nor ToMap methods 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.Models
Appwrite/Models/Row.cs (1)

64-66: Make $permissions extraction null/omission-safe

Guard 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 but ConvertToList<T>() is not used anywhere in this file. The From method 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

📥 Commits

Reviewing files that changed from the base of the PR and between e8f050a and b8a1874.

📒 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 usage

Consistent with other models; no concerns.

Appwrite/Models/ColumnPolygon.cs (1)

8-8: LGTM: import required for ConvertToList

Matches the new deserialization pattern.

Appwrite/Models/ColumnEmail.cs (1)

8-8: LGTM: added Extensions import

Consistent with the codebase changes.

Appwrite/Models/AttributeFloat.cs (1)

8-8: LGTM: import addition

No behavioral change; consistent with repo-wide updates.

Appwrite/Models/Phone.cs (1)

8-8: Import addition looks good.
Bringing in Appwrite.Extensions keeps this model ready for the shared conversion helpers; nothing further needed here.

Appwrite/Models/AttributeBoolean.cs (1)

8-8: Consistent namespace import.
Importing Appwrite.Extensions aligns this model with the shared helpers used elsewhere; no issues.

Appwrite/Models/Language.cs (1)

8-8: Namespace update looks fine.
Including Appwrite.Extensions keeps 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.
Adding Appwrite.Extensions maintains 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.Extensions namespace and the use of ConvertToList<string>() correctly standardizes list deserialization across the codebase. Since RecoveryCodes is 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 by Select and ToList() correctly standardizes the deserialization pattern across the codebase. Since LocaleCodes is 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 by Select and ToList() correctly standardizes the deserialization pattern. Since Countries is 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 by Select and ToList() correctly standardizes the deserialization pattern. Since Frameworks is 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

supports path is correct after centralization. Ensure the ConvertToList() change to use Client.SerializerOptions is in place.

Appwrite/Models/ProviderList.cs (1)

30-31: LGTM

Centralized 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.Extensions namespace and the use of ConvertToList<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.Extensions and the use of ConvertToList<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 $permissions field, 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 the roles field 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 $permissions and allowedFileExtensions now use ConvertToList<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>() and ConvertToList<long>() for attributes and lengths aligns 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.Extensions and the refactored deserialization logic for the vars field using ConvertToList<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 elements field using ConvertToList<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 $permissions field using ConvertToList<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 specifications using ConvertToList<Dictionary<string, object>>() followed by mapping each item to Specification is 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 buckets field using ConvertToList<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 documents field using ConvertToList<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 elements field using ConvertToList<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.Extensions using directive and the refactoring of list field deserialization (permissions, attributes, indexes) to use the ConvertToList<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.Extensions namespace and the use of ConvertToList<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 for columns and lengths properties.

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 for vars via Variable.From is 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 for permissions, requestHeaders, and responseHeaders. The nested mapping through Headers.From for header lists is correctly implemented.

Also applies to: 112-122

Comment on lines +16 to +26
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)}>")
};
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Suggested change
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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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.

Comment on lines +72 to 73
xdefault: map["default"].ConvertToList<object>()
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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>()
+                : null

Also 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.cs

Length 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.cs

Length 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>()
+                : null

Optional: 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.

Suggested change
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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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<' -n5

Length 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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

Suggested change
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).

Comment on lines +30 to 31
currencies: map["currencies"].ConvertToList<Dictionary<string, object>>().Select(it => Currency.From(map: it)).ToList()
);
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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.cs

Length 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>()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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.cs

Length 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.

Suggested change
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.

Comment on lines +88 to 95
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(),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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.

@loks0n loks0n merged commit 59bcf85 into main Oct 13, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants