Skip to content

Conversation

@abnegate
Copy link
Member

@abnegate abnegate commented Oct 22, 2025

What does this PR do?

(Provide a description of what this PR does.)

Test Plan

(Write your test plan here. If you changed any code, please provide us with clear instructions on how you verified your changes work.)

Related PRs and Issues

(If this PR is related to any other PR or resolves any issue or related to any issue link all related PR and issues here.)

Have you read the Contributing Guidelines on issues?

(Write your answer here.)

Summary by CodeRabbit

  • New Features

    • Added Operator helper and Condition enum across SDKs — new publicly exported utilities for building consistent JSON operator descriptors (arithmetic, array, string, boolean/date) in JS/TS, Dart/Flutter, Android/iOS, PHP, Python, Go, Ruby, C#, and others.
  • Tests

    • Added comprehensive Operator unit tests and updated language test fixtures to include operator helper responses, expanding coverage and sample outputs.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 22, 2025

Walkthrough

Adds Operator and Condition templates and file mappings to many SDK generators (Android, Apple/Swift, Dart/Flutter, Deno, DotNet, Go, Kotlin, Node, PHP, Python, React Native, Ruby, Swift, Web). Introduces language-specific Operator implementation templates (and some corresponding tests), updates package/module exports/imports/parts to include Operator/Condition, and extends autogenerated test fixtures and language tests to exercise the new Operator helpers. A new protected constant OPERATOR_HELPER_RESPONSES was added to tests/Base.php. All changes are additive.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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 "Feat operators" is directly related to the primary change in this pull request, which adds comprehensive operator functionality across all SDK language generators. The PR introduces new Operator classes and Condition enums/types for Android, Apple, Dart, Deno, DotNet, Flutter, Go, Kotlin, Node, PHP, Python, ReactNative, Ruby, Swift, and Web SDKs, along with their corresponding templates and tests. The title accurately conveys that this is a feature addition centered on operators, and a developer scanning the commit history would immediately understand that this changeset introduces operator support to the SDK generator.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-operators

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.

Copy link
Contributor

@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: 18

♻️ Duplicate comments (1)
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

5-10: Same serializer considerations as Kotlin file

Please apply the same verification re: empty lists and nulls in arrays.

🧹 Nitpick comments (23)
templates/ruby/lib/container/operator.rb.twig (2)

28-28: Use class << self for singleton methods.

class << Operator works but is unconventional and can confuse constant scope; prefer class << self.

-        class << Operator
+        class << self

17-22: Avoid reliance on Hash#compact or confirm Ruby minimum version.

If supported Ruby targets may be < 2.4/2.5, Hash#compact might be unavailable. Safer inline alternative:

-            {
-                method: @method,
-                values: @values
-            }.compact.to_json(*args)
+            payload = { method: @method }
+            payload[:values] = @values unless @values.nil?
+            payload.to_json(*args)
templates/python/package/operator.py.twig (1)

4-10: Initialize self.values explicitly

Minor clarity: set self.values = None before the conditional, so the attribute always exists.

 class Operator():
     def __init__(self, method, values=None):
         self.method = method
-
-        if values is not None:
-            self.values = values if isinstance(values, list) else [values]
+        self.values = None
+        if values is not None:
+            self.values = values if isinstance(values, list) else [values]
templates/php/src/Operator.php.twig (2)

26-32: Don’t drop empty arrays; only drop null

array_filter() without a callback removes empty arrays, so "values": [] gets omitted (toggle/arrayUnique/dateSetNow). Keep empty arrays to match other SDKs.

-    public function jsonSerialize(): mixed
-    {
-        return array_filter([
-            'method' => $this->method,
-            'values' => $this->values,
-        ]);
-    }
+    public function jsonSerialize(): mixed
+    {
+        // Keep empty arrays; drop only nulls
+        return array_filter([
+            'method' => $this->method,
+            'values' => $this->values,
+        ], fn($v) => $v !== null);
+    }

21-24: Safer stringification

Guard against json_encode() returning false and use unescaped options for consistency.

-    public function __toString(): string
-    {
-        return json_encode($this);
-    }
+    public function __toString(): string
+    {
+        $json = json_encode($this, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+        return $json === false ? '' : $json;
+    }
templates/node/src/operator.ts.twig (1)

1-3: Simplify types

Reduce redundancy; use unknown for flexibility without “any”.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
-export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
+export type OperatorValuesList = unknown[];
+export type OperatorValues = unknown | unknown[];
templates/deno/src/operator.ts.twig (4)

1-3: Tighten types: any[] makes the union redundant.

export type OperatorValuesList = string[] | number[] | boolean[] | any[] collapses to any[]. Prefer ReadonlyArray<unknown> for stronger typing and consistency.

Apply:

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
-export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = ReadonlyArray<unknown>;
+export type OperatorValues = OperatorValuesSingle | OperatorValuesList;

9-11: Prefer immutability for fields.

Mark method and values as readonly and simplify normalization.

-export class Operator {
-  method: string;
-  values: OperatorValuesList | undefined;
+export class Operator {
+  readonly method: string;
+  readonly values?: OperatorValuesList;
@@
-    if (values !== undefined) {
-      if (Array.isArray(values)) {
-        this.values = values;
-      } else {
-        this.values = [values] as OperatorValuesList;
-      }
-    }
+    if (values !== undefined) {
+      this.values = Array.isArray(values) ? values : [values];
+    }

Also applies to: 24-31


199-201: Avoid serializing [condition, null] when value is omitted.

JSON.stringify turns undefined within arrays into null. Build the array conditionally.

-  static arrayFilter = (condition: string, value?: any): string =>
-    new Operator("arrayFilter", [condition, value]).toString();
+  static arrayFilter = (condition: string, value?: any): string => {
+    const values = value === undefined ? [condition] : [condition, value];
+    return new Operator("arrayFilter", values).toString();
+  };

Please confirm server-side expects the second argument to be omitted (not null) when unused.


1-254: De-duplicate TS templates via a Twig partial.

Deno/Web/React‑Native implementations are identical. Extract a single operator.ts.twig partial to prevent drift.

templates/react-native/src/operator.ts.twig (4)

1-3: Tighten types: replace union with ReadonlyArray<unknown>.

-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+export type OperatorValuesList = ReadonlyArray<unknown>;

9-11: Make fields readonly and simplify normalization.

-  method: string;
-  values: OperatorValuesList | undefined;
+  readonly method: string;
+  readonly values?: OperatorValuesList;
@@
-    if (values !== undefined) {
-      if (Array.isArray(values)) {
-        this.values = values;
-      } else {
-        this.values = [values] as OperatorValuesList;
-      }
-    }
+    if (values !== undefined) {
+      this.values = Array.isArray(values) ? values : [values];
+    }

Also applies to: 24-31


199-201: Drop null second arg in arrayFilter.

-  static arrayFilter = (condition: string, value?: any): string =>
-    new Operator("arrayFilter", [condition, value]).toString();
+  static arrayFilter = (condition: string, value?: any): string => {
+    const values = value === undefined ? [condition] : [condition, value];
+    return new Operator("arrayFilter", values).toString();
+  };

1-254: Extract shared TS logic into a Twig partial to avoid drift across targets.

templates/dart/lib/operator.dart.twig (2)

25-41: Align defaults with other languages (value = 1).

TS/C# default increment/decrement to 1. Mirror for Dart to keep SDK parity.

-  static String increment(num value, [num? max]) {
+  static String increment([num value = 1, num? max]) {
@@
-  static String decrement(num value, [num? min]) {
+  static String decrement([num value = 1, num? min]) {

Confirm this change won’t break existing generator expectations/tests.


102-105: Avoid [condition, null] when optional value is not provided.

-  static String arrayFilter(String condition, [dynamic value]) =>
-      Operator._('arrayFilter', [condition, value]).toString();
+  static String arrayFilter(String condition, [dynamic value]) {
+    final values = <dynamic>[condition];
+    if (value != null) values.add(value);
+    return Operator._('arrayFilter', values).toString();
+  }

Ensure tests expect omission (not null) for the second argument.

templates/web/src/operator.ts.twig (4)

1-3: Simplify to ReadonlyArray<unknown>; remove redundant union.

-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+export type OperatorValuesList = ReadonlyArray<unknown>;

9-11: Readonly fields and simpler normalization.

-  method: string;
-  values: OperatorValuesList | undefined;
+  readonly method: string;
+  readonly values?: OperatorValuesList;
@@
-    if (values !== undefined) {
-      if (Array.isArray(values)) {
-        this.values = values;
-      } else {
-        this.values = [values] as OperatorValuesList;
-      }
-    }
+    if (values !== undefined) {
+      this.values = Array.isArray(values) ? values : [values];
+    }

Also applies to: 24-31


199-201: Conditional arrayFilter second parameter to avoid nulls.

-  static arrayFilter = (condition: string, value?: any): string =>
-    new Operator("arrayFilter", [condition, value]).toString();
+  static arrayFilter = (condition: string, value?: any): string => {
+    const values = value === undefined ? [condition] : [condition, value];
+    return new Operator("arrayFilter", values).toString();
+  };

1-254: Extract a shared TS Twig partial for Operator to keep Deno/Web/RN in sync.

templates/dotnet/Package/Operator.cs.twig (2)

13-15: Ensure values nulls are not serialized.

For parity with other SDKs, omit values when null. Add attribute guard.

-        [JsonPropertyName("values")]
-        public List<object>? Values { get; set; }
+        [JsonPropertyName("values")]
+        [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+        public List<object>? Values { get; set; }

If Client.SerializerOptions already ignores nulls, this is optional but makes it explicit.


133-136: Avoid [condition, null] when value is not provided.

-        public static string ArrayFilter(string condition, object? value = null)
-        {
-            return new Operator("arrayFilter", new List<object> { condition, value! }).ToString();
-        }
+        public static string ArrayFilter(string condition, object? value = null)
+        {
+            var values = new List<object> { condition };
+            if (value is not null) values.Add(value);
+            return new Operator("arrayFilter", values).ToString();
+        }

Confirm the API expects omission, not JSON null, for the optional arg.

templates/go/operator.go.twig (1)

117-123: Consider validating the index parameter.

ArrayInsert accepts an index parameter but doesn't validate if it's negative or otherwise invalid. While server-side validation may handle this, an early client-side check could improve developer experience.

 func ArrayInsert(index int, value interface{}) string {
+	if index < 0 {
+		// Consider: panic, return error, or let server validate
+	}
 	values := []interface{}{index, value}
 	return parseOperator(operatorOptions{
 		Method: "arrayInsert",
 		Values: &values,
 	})
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 997e27a and bbb6700.

📒 Files selected for processing (82)
  • src/SDK/Language/Android.php (1 hunks)
  • src/SDK/Language/Apple.php (1 hunks)
  • src/SDK/Language/Dart.php (2 hunks)
  • src/SDK/Language/Deno.php (1 hunks)
  • src/SDK/Language/DotNet.php (1 hunks)
  • src/SDK/Language/Flutter.php (2 hunks)
  • src/SDK/Language/Go.php (1 hunks)
  • src/SDK/Language/Kotlin.php (1 hunks)
  • src/SDK/Language/Node.php (1 hunks)
  • src/SDK/Language/PHP.php (1 hunks)
  • src/SDK/Language/Python.php (1 hunks)
  • src/SDK/Language/ReactNative.php (1 hunks)
  • src/SDK/Language/Ruby.php (1 hunks)
  • src/SDK/Language/Swift.php (1 hunks)
  • src/SDK/Language/Web.php (1 hunks)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/dart/test/operator_test.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/deno/test/operator.test.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/php/tests/OperatorTest.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
  • tests/Android14Java11Test.php (1 hunks)
  • tests/Android14Java17Test.php (1 hunks)
  • tests/Android14Java8Test.php (1 hunks)
  • tests/Android5Java17Test.php (1 hunks)
  • tests/AppleSwift56Test.php (1 hunks)
  • tests/Base.php (1 hunks)
  • tests/DartBetaTest.php (1 hunks)
  • tests/DartStableTest.php (1 hunks)
  • tests/Deno1193Test.php (1 hunks)
  • tests/Deno1303Test.php (1 hunks)
  • tests/DotNet60Test.php (1 hunks)
  • tests/DotNet80Test.php (1 hunks)
  • tests/DotNet90Test.php (1 hunks)
  • tests/FlutterBetaTest.php (1 hunks)
  • tests/FlutterStableTest.php (1 hunks)
  • tests/Go112Test.php (1 hunks)
  • tests/Go118Test.php (1 hunks)
  • tests/KotlinJava11Test.php (1 hunks)
  • tests/KotlinJava17Test.php (1 hunks)
  • tests/KotlinJava8Test.php (1 hunks)
  • tests/Node16Test.php (1 hunks)
  • tests/Node18Test.php (1 hunks)
  • tests/Node20Test.php (1 hunks)
  • tests/PHP80Test.php (1 hunks)
  • tests/PHP83Test.php (1 hunks)
  • tests/Python310Test.php (1 hunks)
  • tests/Python311Test.php (1 hunks)
  • tests/Python312Test.php (1 hunks)
  • tests/Python313Test.php (1 hunks)
  • tests/Python39Test.php (1 hunks)
  • tests/Ruby27Test.php (1 hunks)
  • tests/Ruby30Test.php (1 hunks)
  • tests/Ruby31Test.php (1 hunks)
  • tests/Swift56Test.php (1 hunks)
  • tests/WebChromiumTest.php (1 hunks)
  • tests/WebNodeTest.php (1 hunks)
  • tests/languages/android/Tests.kt (2 hunks)
  • tests/languages/apple/Tests.swift (1 hunks)
  • tests/languages/dart/tests.dart (1 hunks)
  • tests/languages/deno/tests.ts (2 hunks)
  • tests/languages/dotnet/Tests.cs (1 hunks)
  • tests/languages/flutter/tests.dart (1 hunks)
  • tests/languages/go/tests.go (3 hunks)
  • tests/languages/kotlin/Tests.kt (2 hunks)
  • tests/languages/node/test.js (2 hunks)
  • tests/languages/php/test.php (3 hunks)
  • tests/languages/python/tests.py (2 hunks)
  • tests/languages/ruby/tests.rb (1 hunks)
  • tests/languages/swift/Tests.swift (1 hunks)
  • tests/languages/web/index.html (1 hunks)
  • tests/languages/web/node.js (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (38)
tests/AppleSwift56Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Android14Java8Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Ruby31Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/KotlinJava17Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Node16Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/PHP80Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/PHP83Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/KotlinJava8Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Go112Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Deno1303Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Ruby30Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Go118Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Swift56Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/DotNet80Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/DartStableTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/FlutterBetaTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/WebNodeTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Python310Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Node18Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Ruby27Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Android5Java17Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/DotNet90Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/languages/web/node.js (1)
tests/languages/node/test.js (3)
  • require (1-12)
  • require (13-13)
  • require (14-14)
tests/WebChromiumTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/languages/android/Tests.kt (1)
tests/languages/kotlin/Tests.kt (1)
  • writeToFile (271-274)
tests/Node20Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Python311Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/KotlinJava11Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Android14Java17Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Python39Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Python313Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/FlutterStableTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/languages/kotlin/Tests.kt (1)
tests/languages/android/Tests.kt (1)
  • writeToFile (304-307)
tests/DartBetaTest.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Android14Java11Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Python312Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/Deno1193Test.php (1)
tests/Base.php (1)
  • Base (17-326)
tests/DotNet60Test.php (1)
tests/Base.php (1)
  • Base (17-326)
🪛 detekt (1.23.8)
tests/languages/android/Tests.kt

[warning] 279-279: The caught exception is swallowed. The original exception could be lost.

(detekt.exceptions.SwallowedException)

🔇 Additional comments (76)
tests/Go112Test.php (1)

30-31: LGTM: test now validates operator helper outputs.

Including OPERATOR_HELPER_RESPONSES keeps Go tests aligned with new Operator helpers.

tests/DotNet60Test.php (1)

32-34: LGTM: added Operator expectations for .NET 6 suite.

Spread of OPERATOR_HELPER_RESPONSES matches Base fixtures.

tests/Python39Test.php (1)

32-34: LGTM: Python 3.9 tests include operator fixtures.

Keeps parity with other language test suites.

tests/PHP80Test.php (1)

28-29: LGTM! Consistent integration of operator helper responses.

The addition of OPERATOR_HELPER_RESPONSES to the expected output follows the established pattern used for Query, Permission, and ID helpers. This change enables validation of the new Operator functionality in PHP SDK tests.

tests/Go118Test.php (1)

30-30: LGTM! Go SDK test expectations updated correctly.

The integration of OPERATOR_HELPER_RESPONSES is consistent with the broader operator feature rollout across all SDK languages.

src/SDK/Language/Flutter.php (2)

88-92: LGTM! Operator library file registration follows established conventions.

The operator library file is registered consistently with other helper utilities (Query, Permission, ID, Role). The placement in the file structure is logical and maintains the existing organization pattern.


283-287: LGTM! Operator test file properly registered.

The test file registration mirrors the pattern used for other helper tests (id_test.dart, permission_test.dart, query_test.dart), ensuring comprehensive test coverage for the new Operator functionality.

tests/PHP83Test.php (1)

28-29: LGTM! PHP 8.3 test expectations updated consistently.

The addition aligns with the operator helper integration across all PHP SDK test variants.

tests/DotNet80Test.php (1)

32-33: LGTM! .NET SDK test expectations properly extended.

The operator helper responses are correctly integrated following the established test pattern.

tests/Ruby27Test.php (1)

30-31: LGTM! Ruby SDK test expectations updated correctly.

Consistent integration of operator helper validation for the Ruby SDK.

tests/FlutterStableTest.php (1)

33-34: LGTM! Flutter test expectations properly updated.

The operator helper responses are correctly added to validate the Flutter SDK's operator functionality.

tests/Android14Java17Test.php (1)

34-35: LGTM! Android SDK test expectations properly extended.

The addition of OPERATOR_HELPER_RESPONSES completes the consistent operator helper integration across all language SDKs.

tests/KotlinJava11Test.php (1)

33-34: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES to the expected output follows the established pattern and correctly uses the spread operator with proper syntax.

tests/Python310Test.php (1)

32-33: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/Ruby30Test.php (1)

30-31: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/Android5Java17Test.php (1)

34-35: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/Python312Test.php (1)

32-33: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/Ruby31Test.php (1)

30-31: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/DartBetaTest.php (1)

32-33: LGTM! Test expectations extended correctly.

The addition of OPERATOR_HELPER_RESPONSES follows the established pattern and is consistent with other test suite updates.

tests/Node20Test.php (1)

36-37: LGTM! Consistent addition of operator test expectations.

The addition of OPERATOR_HELPER_RESPONSES to the expected output follows the established pattern and correctly extends the test suite to validate operator functionality.

tests/Android14Java8Test.php (1)

35-36: LGTM! Consistent operator test integration.

The operator helper responses are correctly added to the expected output, maintaining consistency with other test suites.

tests/WebNodeTest.php (1)

37-38: LGTM! Operator test expectations added correctly.

The addition maintains consistency with the pattern established across all test suites.

tests/Swift56Test.php (1)

32-33: LGTM! Consistent operator test addition.

The operator helper responses are correctly integrated into the Swift test expectations.

src/SDK/Language/Deno.php (2)

76-80: LGTM! Operator test file generation added correctly.

The test file generation entry properly mirrors the pattern established by query tests. The verification script above will confirm both templates exist.


66-70: Template exists and configuration is correct.

Verification confirms that deno/src/operator.ts.twig exists at the expected location. The operator source file generation is correctly configured in the Deno language driver.

tests/KotlinJava17Test.php (1)

33-34: LGTM! Operator test expectations integrated consistently.

The addition of operator helper responses follows the established pattern across all test suites.

src/SDK/Language/Python.php (1)

163-167: Template file verified—no further action needed.

The operator.py.twig template file exists and is correctly referenced. The operator file generation entry is properly structured and placed logically after query.py generation.

src/SDK/Language/Ruby.php (1)

150-154: Template verified and correctly implemented.

The Ruby operator template file exists at templates/ruby/lib/container/operator.rb.twig and the file generation entry is properly structured with correct path reference.

tests/Node18Test.php (1)

36-37: LGTM!

The addition of OPERATOR_HELPER_RESPONSES to the expected output array correctly extends the test to validate operator helper functionality.

tests/Deno1193Test.php (1)

28-29: LGTM!

The operator helper responses are correctly integrated into the expected output array.

tests/Python313Test.php (1)

32-33: LGTM!

The operator helper responses are properly added to the expected output for Python 3.13 tests.

tests/Deno1303Test.php (1)

28-29: LGTM!

The operator helper responses are correctly integrated for Deno 1.30.3 tests.

tests/Node16Test.php (1)

36-37: LGTM!

The operator helper responses are correctly added to the Node 16 test expectations.

tests/Python311Test.php (1)

32-33: LGTM!

The operator helper responses are properly integrated for Python 3.11 tests.

src/SDK/Language/Kotlin.php (1)

397-401: LGTM!

The Operator.kt file generation entry follows the established pattern for other helper classes (ID, Query, Permission, Role) and is correctly configured.

tests/FlutterBetaTest.php (1)

33-34: LGTM!

The operator helper responses are correctly added to the Flutter beta test expectations.

tests/DotNet90Test.php (1)

32-33: LGTM!

The addition of OPERATOR_HELPER_RESPONSES to the expected output is correct and consistent with the broader PR changes introducing Operator support across all SDK implementations.

tests/AppleSwift56Test.php (1)

33-34: LGTM!

The addition of OPERATOR_HELPER_RESPONSES to the expected output is correctly implemented and aligns with the PR's objective of adding Operator support.

tests/DartStableTest.php (1)

32-33: LGTM!

The change correctly adds OPERATOR_HELPER_RESPONSES to the expected test output, maintaining consistency with the PR-wide Operator feature addition.

tests/WebChromiumTest.php (1)

37-38: LGTM!

The addition of OPERATOR_HELPER_RESPONSES is correctly implemented and consistent with other Web SDK test configurations in this PR.

src/SDK/Language/Swift.php (1)

175-179: LGTM!

The Operator.swift file generation entry is correctly configured and logically positioned among other helper classes (Query, ID). This aligns with the PR's objective of adding Operator support to the Swift SDK.

src/SDK/Language/Apple.php (1)

78-82: LGTM!

The Operator.swift file generation entry is correctly configured for the Apple SDK, mirroring the Swift implementation. The placement and structure are consistent with the parent Swift class.

tests/KotlinJava8Test.php (1)

33-34: LGTM!

The addition of OPERATOR_HELPER_RESPONSES to the expected output is correctly implemented and consistent with the Kotlin SDK test configuration pattern.

src/SDK/Language/ReactNative.php (1)

68-72: LGTM!

The operator.ts file generation entry is consistent with the existing file mapping patterns and properly positioned alongside other helper utilities (query.ts, id.ts, etc.).

src/SDK/Language/Go.php (1)

101-105: LGTM!

The operator.go file generation entry is properly formatted and consistent with the existing Go file mapping patterns.

tests/Base.php (1)

166-192: LGTM!

The OPERATOR_HELPER_RESPONSES constant is properly formatted and follows the same pattern as the existing helper response constants (QUERY_HELPER_RESPONSES, PERMISSION_HELPER_RESPONSES, ID_HELPER_RESPONSES).

templates/deno/test/operator.test.ts.twig (1)

1-130: LGTM!

The Deno operator test template is well-structured and comprehensive. All test invocations correctly match the expected OPERATOR_HELPER_RESPONSES defined in tests/Base.php. The tests properly verify that the toString() serialization outputs the correct JSON format for all operator methods.

tests/languages/dotnet/Tests.cs (1)

228-254: LGTM! Comprehensive Operator test coverage.

The Operator helper tests are well-structured and cover a comprehensive set of operations including arithmetic, array manipulation, string operations, boolean toggle, and date utilities. The test patterns are consistent with the existing Query, Permission, Role, and ID helper tests in this file.

tests/languages/go/tests.go (3)

12-12: LGTM! Operator import added correctly.

The operator package import is properly placed with other helper imports.


148-149: LGTM! Operator tests properly integrated.

The testOperatorHelpers() call is correctly positioned after other helper tests, maintaining consistency with the test flow.


282-309: LGTM! Comprehensive Operator test implementation.

The testOperatorHelpers() function provides thorough coverage of all Operator operations using Go-appropriate syntax, including the use of []interface{} for array parameters.

src/SDK/Language/Node.php (1)

205-209: LGTM! Operator file generation entry properly configured.

The new file entry for operator.ts follows the established pattern for other helper files (query, id, permission, role) and is correctly positioned in the file generation list.

tests/languages/web/node.js (2)

1-1: LGTM! Operator import added correctly.

The Operator class is properly added to the destructured imports from the SDK module.


253-279: LGTM! Comprehensive Operator test coverage.

The Operator helper tests are well-implemented with JavaScript-appropriate syntax and provide thorough coverage of all operator operations. The tests are correctly positioned in the test flow.

src/SDK/Language/Android.php (1)

128-132: LGTM! Operator.kt generation entry properly configured.

The new file entry for Operator.kt follows the established pattern for other Android library helper files and is correctly positioned after the Query.kt entry.

src/SDK/Language/Dart.php (2)

345-349: LGTM! Operator source file entry properly configured.

The new file entry for operator.dart follows the established pattern for other Dart helper files and is correctly positioned after the query.dart entry.


440-444: LGTM! Operator test file entry properly configured.

The new file entry for operator_test.dart follows the established pattern for other Dart test files and is correctly positioned after the query_test.dart entry.

tests/languages/android/Tests.kt (2)

11-11: LGTM! Operator import added correctly.

The Operator import is properly placed with other helper imports.


271-297: LGTM! Comprehensive Operator test implementation.

The Operator helper tests are well-implemented with Kotlin-appropriate syntax (using listOf() for arrays) and provide thorough coverage of all operator operations. The tests properly use the writeToFile() helper consistent with other tests in this file.

tests/languages/apple/Tests.swift (1)

251-277: LGTM! Comprehensive Operator test implementation.

The Operator helper tests are well-implemented with Swift-appropriate syntax, including named parameters (max:, min:) where applicable. The tests provide thorough coverage of all operator operations and are correctly positioned in the test flow.

tests/languages/python/tests.py (1)

11-11: LGTM! Operator tests added correctly.

The import and test calls align with the expected operator helper responses.

Also applies to: 201-227

templates/dart/test/operator_test.dart.twig (1)

1-160: LGTM! Comprehensive Operator test template.

The test suite provides thorough coverage of all Operator methods with proper JSON decoding and assertions.

src/SDK/Language/PHP.php (1)

215-224: LGTM! Operator file generation entries added correctly.

The new entries follow the same pattern as existing helper classes (ID, Query, Role, Permission).

templates/php/tests/OperatorTest.php.twig (1)

1-92: LGTM! Comprehensive PHP Operator test template.

The test suite validates all Operator methods with strict JSON output assertions.

tests/Android14Java11Test.php (1)

35-36: LGTM! Expected output updated for Operator tests.

The addition of OPERATOR_HELPER_RESPONSES correctly extends the expected test output.

tests/languages/php/test.php (2)

10-10: Operator import/use — OK

Includes and namespace use look correct and consistent with generated class.

Also applies to: 24-24


219-245: Add parity checks for null and empty-args cases

Please add invocations that exercise:

  • arrayFilter with only the condition (to validate second argument serialized as null).
  • zero-arg ops (toggle, arrayUnique, dateSetNow) to confirm whether "values": [] is present across languages.

This helps catch cross-language JSON shape drift early.

templates/python/package/operator.py.twig (1)

11-16: LGTM

Compact, deterministic JSON; matches the intended contract.

templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (2)

5-10: Verify serializer preserves empty lists and nulls in arrays

Ensure {{ sdk.namespace | caseDot }}.extensions.toJson:

  • Does not drop empty lists (values: []).
  • Preserves null elements inside arrays (e.g., ["equals", null]).

If it filters empties/nulls, tests will diverge from other SDKs.


11-101: API surface — OK

Factory methods/readability look consistent and idiomatic.

templates/node/src/operator.ts.twig (1)

38-43: LGTM

Serialization is compact; undefined omits the property as intended.

templates/dotnet/Package/Operator.cs.twig (1)

38-41: No issues found; Client.SerializerOptions is properly configured.

Verification confirms Client.SerializerOptions exists in the Client class and is configured with DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, ensuring null values are consistently ignored during serialization. The implementation in Operator.cs.twig is correct.

templates/dart/lib/operator.dart.twig (1)

22-24: No action needed — dart:convert is properly imported in the parent library.

The operator.dart.twig file is a Dart "part" file and inherits imports from its parent library. The parent library file (package.dart.twig) contains import 'dart:convert' at line 11, which makes jsonEncode() available to the toString() method on line 22 of operator.dart.twig. The code is correct as written.

templates/go/operator.go.twig (3)

40-101: LGTM: Arithmetic operators follow consistent pattern.

The arithmetic operator functions (Increment, Decrement, Multiply, Divide, Modulo, Power) are correctly implemented with consistent handling of optional parameters.


163-185: LGTM: String and boolean operators correctly implemented.

The Concat, Replace, and Toggle functions follow the expected patterns and have appropriate type signatures.


187-209: LGTM: Date operators correctly implemented.

The date manipulation functions (DateAddDays, DateSubDays, DateSetNow) are properly implemented with appropriate type signatures.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

1-104: Identical to Kotlin template - same review applies.

This file is identical to templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig. The same review comments apply:

  1. ✅ Clean operator builder pattern with good API design
  2. ⚠️ Division/modulo by zero validation needed (lines 30-38)
  3. ⚠️ Array index validation should be verified (line 54)
  4. 🔄 Template duplication should be eliminated (see comments on the other file)

Please refer to the review comments on templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig for detailed analysis and suggested fixes.

🧹 Nitpick comments (1)
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

1-104: Consider eliminating template duplication.

This file is identical to templates/android/library/src/main/java/io/package/Operator.kt.twig. Having two copies of the same 104-line template creates maintenance overhead and risks divergence.

Consider one of these approaches:

Option 1: Extract to a shared template fragment

{# Create templates/shared/operator.kt.twig #}
{% include 'shared/operator.kt.twig' %}

Option 2: Use template inheritance

{# In both files #}
{% extends 'base/operator.kt.twig' %}

Option 3: Generate both from a single source
If the build system supports it, generate both target files from a single template definition.

This ensures bug fixes and feature additions only need to be applied once.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bbb6700 and c6398f6.

📒 Files selected for processing (5)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/dart/lib/package.dart.twig (1 hunks)
  • templates/flutter/lib/package.dart.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
🔇 Additional comments (10)
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (3)

1-10: LGTM! Clean operator builder pattern.

The class structure is well-designed with a simple data holder that delegates JSON serialization to the toJson() extension method. The companion object factory pattern provides a clear API for creating operator descriptors.


30-38: Verify division-by-zero and modulo-by-zero handling.

The divide and modulo methods accept divisor without validating that it's non-zero. If these operators are executed without validation elsewhere, this could lead to runtime exceptions.

Please confirm whether zero-division validation occurs:

  • At the server/API level when these operators are processed
  • At runtime before execution
  • Or if client-side validation should be added here

If validation doesn't occur elsewhere, consider adding checks:

 fun divide(divisor: Number, min: Number? = null): String {
+    require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" }
     val values = mutableListOf<Any>(divisor)
     min?.let { values.add(it) }
     return Operator("divide", values).toJson()
 }

 fun modulo(divisor: Number): String {
+    require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" }
     return Operator("modulo", listOf(divisor)).toJson()
 }

54-56: Verify array index validation.

The arrayInsert method accepts an index without validation. Negative indices or out-of-bounds values could cause runtime errors when the operator is applied.

Please confirm whether index validation occurs at runtime when the operator is executed, or if client-side validation should be added here to catch negative indices early:

 fun arrayInsert(index: Int, value: Any): String {
+    require(index >= 0) { "Index must be non-negative" }
     return Operator("arrayInsert", listOf(index, value)).toJson()
 }
templates/flutter/lib/package.dart.twig (1)

33-33: LGTM!

The addition of the operator.dart part directive cleanly extends the Flutter library composition to include Operator functionality, mirroring the pattern used for other helper components (query, permission, role, id).

templates/dart/lib/package.dart.twig (1)

30-30: LGTM!

The addition of the operator.dart part directive properly integrates the Operator class into the Dart library, maintaining consistency with the existing part structure.

templates/dart/lib/operator.dart.twig (5)

1-8: Well-structured class foundation.

The private constructor pattern with flexible values parameter (supporting lists, scalars, or null) provides a clean foundation for the factory methods. The use of dynamic for values is appropriate here given the variety of types that need to be supported.


10-23: Excellent defensive JSON serialization.

The toJson method includes smart defensive logic at line 16 that ensures values are always serialized as lists while preserving the semantic distinction between empty arrays and null (omitted field). The implementation correctly handles all edge cases.


25-72: Numeric operators correctly implemented.

All six numeric operators follow a consistent pattern and properly handle optional boundary parameters (max for increment/multiply/power, min for decrement/divide). The conditional list building logic is correct and the method signatures are semantically appropriate for their respective operations.


74-109: Array operators are well-implemented.

All eight array operators are correctly implemented with appropriate signatures. The distinction between methods that accept lists directly (append, prepend, intersect, diff) versus those that construct argument lists (insert, remove, filter) is handled properly. The empty list in arrayUnique() appears intentional for API compatibility.


111-133: String, boolean, and date operators look good.

The final set of operators (concat, replace, toggle, dateAddDays, dateSubDays, dateSetNow) are correctly implemented and follow the same consistent patterns established by the numeric and array operators. The use of empty lists for parameter-less operations maintains consistency across the API surface.

Copy link
Contributor

@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: 3

♻️ Duplicate comments (3)
tests/languages/deno/tests.ts (1)

244-271: Fix parameter mismatches in Operator test calls.

The parameter values in multiple Operator test calls don't align with the expected OPERATOR_HELPER_RESPONSES. The past review comment has already identified all the specific mismatches that need to be corrected, including:

  • Line 248: decrement(5, 0) should be decrement(3, 0)
  • Line 251: modulo(3) should be modulo(5)
  • Lines 253-266: Multiple incorrect parameter values for append, prepend, insert, remove, intersect, diff, filter, concat, and replace methods

Please apply the corrections provided in the previous review.

templates/go/operator.go.twig (1)

1-224: Past review comments still apply.

The critical issues identified in previous reviews remain valid:

  1. The unused toArray function at lines 19-28 should be removed
  2. The ignored json.Marshal error at line 47 needs proper handling
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

58-90: Verify method naming consistency with tests.

This Kotlin template defines array operation methods with an "array" prefix (arrayAppend, arrayPrepend, arrayInsert, arrayRemove, arrayIntersect, arrayDiff, arrayFilter), which is consistent with the Android template but mismatched with the test calls in tests/languages/kotlin/Tests.kt (lines 248-259) that use short names without the prefix.

This is the same naming issue flagged for the Android template and the test file.

🧹 Nitpick comments (1)
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

74-76: Consider using null instead of emptyList() for consistency.

Methods like arrayUnique(), toggle(), and dateSetNow() pass emptyList() as the values parameter, but since values is nullable (List<Any>?), passing null might be more semantically clear and ensure consistent JSON serialization (omitting the field vs. including an empty array).

Example for arrayUnique():

-        fun arrayUnique(): String {
-            return Operator("arrayUnique", emptyList()).toJson()
-        }
+        fun arrayUnique(): String {
+            return Operator("arrayUnique", null).toJson()
+        }

Note: Only apply this change if the API expects the values field to be omitted rather than present as an empty array. Verify the expected JSON format before making this change.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6398f6 and e6a0c1f.

📒 Files selected for processing (30)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/dart/test/operator_test.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/deno/test/operator.test.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/php/tests/OperatorTest.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
  • tests/languages/android/Tests.kt (2 hunks)
  • tests/languages/apple/Tests.swift (1 hunks)
  • tests/languages/dart/tests.dart (1 hunks)
  • tests/languages/deno/tests.ts (2 hunks)
  • tests/languages/dotnet/Tests.cs (1 hunks)
  • tests/languages/flutter/tests.dart (1 hunks)
  • tests/languages/go/tests.go (3 hunks)
  • tests/languages/kotlin/Tests.kt (2 hunks)
  • tests/languages/node/test.js (2 hunks)
  • tests/languages/php/test.php (3 hunks)
  • tests/languages/python/tests.py (2 hunks)
  • tests/languages/ruby/tests.rb (1 hunks)
  • tests/languages/swift/Tests.swift (1 hunks)
  • tests/languages/web/node.js (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (17)
  • tests/languages/dotnet/Tests.cs
  • templates/deno/test/operator.test.ts.twig
  • tests/languages/flutter/tests.dart
  • tests/languages/web/node.js
  • tests/languages/apple/Tests.swift
  • templates/dart/test/operator_test.dart.twig
  • tests/languages/dart/tests.dart
  • templates/python/package/operator.py.twig
  • templates/react-native/src/operator.ts.twig
  • tests/languages/php/test.php
  • tests/languages/node/test.js
  • tests/languages/go/tests.go
  • tests/languages/ruby/tests.rb
  • templates/php/src/Operator.php.twig
  • templates/php/tests/OperatorTest.php.twig
  • tests/languages/android/Tests.kt
  • tests/languages/python/tests.py
🧰 Additional context used
🧬 Code graph analysis (1)
tests/languages/kotlin/Tests.kt (1)
tests/languages/android/Tests.kt (1)
  • writeToFile (305-308)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: python (server)
  • GitHub Check: kotlin (server)
  • GitHub Check: node (server)
  • GitHub Check: swift (server)
  • GitHub Check: flutter (client)
  • GitHub Check: apple (client)
  • GitHub Check: build (8.3, Ruby27)
  • GitHub Check: react-native (client)
  • GitHub Check: build (8.3, Ruby31)
  • GitHub Check: build (8.3, Ruby30)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, PHP83)
  • GitHub Check: build (8.3, Python39)
  • GitHub Check: build (8.3, DotNet80)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, Android5Java17)
🔇 Additional comments (9)
tests/languages/deno/tests.ts (1)

12-13: LGTM!

The Operator and Condition alias declarations follow the established pattern and are properly used in the test suite below.

templates/ruby/lib/container/operator.rb.twig (1)

101-105: LGTM - Past issue resolved.

The array_filter method now correctly omits the second element when value is nil, matching the pattern used across other language implementations.

templates/dart/lib/operator.dart.twig (1)

1-151: Well-structured implementation with comprehensive documentation.

The Dart Operator implementation correctly handles optional parameters and provides clear documentation for all factory methods. The value normalization in toJson ensures consistent serialization.

templates/deno/src/operator.ts.twig (1)

1-269: LGTM - Clean TypeScript implementation.

The Deno Operator template provides proper type safety with comprehensive type definitions and well-documented factory methods. The constructor correctly handles value normalization.

templates/node/src/operator.ts.twig (1)

1-269: LGTM - Consistent with Deno implementation.

The Node Operator template follows the same solid patterns as the Deno implementation, ensuring consistency across TypeScript-based SDKs.

templates/swift/Sources/Operator.swift.twig (1)

212-218: Consistent with cross-language pattern.

The arrayFilter implementation matches the behavior across all other language templates (Ruby, Dart, TypeScript variants, .NET), conditionally including the second parameter only when provided. While past comments suggested always including a null placeholder, the current consistent approach appears to be the accepted design.

tests/languages/swift/Tests.swift (1)

242-246: Verify test parameter values match expected responses.

The past review comments indicate several parameter mismatches with expected OPERATOR_HELPER_RESPONSES. After fixing the method names, verify these parameter values align with the test expectations defined in tests/Base.php.

templates/dotnet/Package/Operator.cs.twig (1)

1-209: LGTM - Solid C# implementation.

The .NET Operator template follows C# best practices with proper enum attributes, extension methods for type-safe string conversion, and consistent value normalization. The use of Client.SerializerOptions ensures serialization consistency across the SDK.

templates/web/src/operator.ts.twig (1)

1-269: LGTM - Consistent TypeScript implementation.

The Web Operator template maintains consistency with the Deno and Node implementations, providing a unified TypeScript API surface across browser, Deno, and Node.js environments.

Copy link
Contributor

@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: 2

♻️ Duplicate comments (3)
tests/languages/dart/tests.dart (1)

221-221: Fix remaining mismatched test invocations.

Lines 221, 223, and 226 still contain incorrect parameters that don't match the expected OPERATOR_HELPER_RESPONSES referenced in the previous review:

  • Line 221: Operator.multiply(2) should be Operator.multiply(3, 1000) to match expected [3,1000]
  • Line 223: Operator.divide(2) should be Operator.divide(4, 1) to match expected [4,1]
  • Line 226: Operator.power(2) should be Operator.power(3, 100) to match expected [3,100]

Apply this diff to fix the remaining issues:

-  print(Operator.multiply(2));
   print(Operator.multiply(3, 1000));
-  print(Operator.divide(2));
   print(Operator.divide(4, 1));
   print(Operator.modulo(5));
-  print(Operator.power(2));
   print(Operator.power(3, 100));

Also applies to: 223-223, 226-226

templates/swift/Sources/Operator.swift.twig (2)

13-61: Good: null handling added for decode/encode.

case null, decodeNil(), and encodeNil() are in place.


231-237: Emit explicit null placeholder for arrayFilter value.

For cross-SDK parity, when value is omitted, second element should be JSON null (e.g., ["equals", null]). Current code drops it.

Apply:

-    public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
-        var values: [Any] = [condition.rawValue]
-        if let value = value {
-            values.append(value)
-        }
-        return Operator(method: "arrayFilter", values: values).description
-    }
+    public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
+        let placeholder: Any = value ?? NSNull()
+        return Operator(method: "arrayFilter", values: [condition.rawValue, placeholder]).description
+    }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6a0c1f and f23cb97.

📒 Files selected for processing (18)
  • templates/deno/mod.ts.twig (2 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/node/src/index.ts.twig (1 hunks)
  • templates/react-native/src/index.ts.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/index.ts.twig (1 hunks)
  • tests/languages/android/Tests.kt (2 hunks)
  • tests/languages/apple/Tests.swift (1 hunks)
  • tests/languages/dart/tests.dart (1 hunks)
  • tests/languages/deno/tests.ts (2 hunks)
  • tests/languages/dotnet/Tests.cs (1 hunks)
  • tests/languages/flutter/tests.dart (1 hunks)
  • tests/languages/go/tests.go (3 hunks)
  • tests/languages/kotlin/Tests.kt (2 hunks)
  • tests/languages/node/test.js (2 hunks)
  • tests/languages/ruby/tests.rb (1 hunks)
  • tests/languages/swift/Tests.swift (1 hunks)
  • tests/languages/web/node.js (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • tests/languages/go/tests.go
  • tests/languages/ruby/tests.rb
  • tests/languages/flutter/tests.dart
  • tests/languages/web/node.js
🧰 Additional context used
🧬 Code graph analysis (2)
tests/languages/kotlin/Tests.kt (1)
tests/languages/android/Tests.kt (1)
  • writeToFile (304-307)
tests/languages/android/Tests.kt (1)
tests/languages/kotlin/Tests.kt (1)
  • writeToFile (271-274)
🔇 Additional comments (16)
tests/languages/apple/Tests.swift (1)

251-277: No issues found with type availability.

The verification confirms that Operator and Condition types are properly exported as public in the Swift templates. The Condition enum is defined as public enum Condition: String, Codable with the equal case matching the test usage, and the Operator struct is defined as public struct Operator : Codable, CustomStringConvertible. These types will be available from the Appwrite or AppwriteEnums imports used in the test file.

tests/languages/dotnet/Tests.cs (1)

228-253: Operator and Condition types verified—no issues found.

The Operator class and Condition enum both exist in templates/dotnet/Package/Operator.cs.twig, and the ArrayFilter method signature correctly accepts a Condition parameter followed by an optional value. The test usage on line 247 (Operator.ArrayFilter(Condition.Equal, "test")) matches the method signature. The test pattern is consistent with other helper tests in this file.

tests/languages/kotlin/Tests.kt (2)

8-9: LGTM! Imports correctly added.

The new imports for Operator and Condition are properly added and used in the test block below.


239-265: All test method calls verified and correct.

Examined the Operator template (templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig) and confirmed all 25 Operator method calls in the test block (lines 239-265) match their corresponding signatures exactly. Parameter counts, types, and method names are all correct. The code is ready as-is.

templates/node/src/index.ts.twig (1)

10-10: Export looks correct; confirm Condition is a runtime enum.

If Condition is a type alias, switch to export type { Condition }. Tests use Condition.Equal, so it must be a value (enum/const). Also confirm templates/node/src/operator.ts.twig is included in mappings.

tests/languages/node/test.js (2)

1-2: OK on added imports.

Operator/Condition inclusion from dist index matches the new public surface.

Please confirm the generated Node template exposes Condition.Equal (casing) at runtime.

Also applies to: 7-8


329-355: Code verification passed—no issues found.

All Operator method definitions (arrayAppend, arrayPrepend, arrayInsert, arrayRemove, arrayUnique, arrayIntersect, arrayDiff) and the Condition enum with Equal value are present and correctly named in the template. Test assertions match the template implementations.

tests/languages/swift/Tests.swift (1)

238-264: Operator test calls updated correctly.

Names and parameters match the new Swift Operator API and prior expectations.

Please confirm outputs match OPERATOR_HELPER_RESPONSES in tests/Base.php for Swift.

templates/deno/mod.ts.twig (2)

6-6: LGTM! Import follows established pattern.

The Operator and Condition import is consistent with other helper imports in the module.


22-23: LGTM! Exports complete the public API.

The Operator and Condition exports properly expose the new helper functionality.

templates/react-native/src/index.ts.twig (1)

11-11: LGTM! Export follows consistent pattern.

The Operator and Condition export aligns with the module's export structure.

templates/web/src/index.ts.twig (1)

17-17: LGTM! Export consistent with module structure.

The Operator and Condition export properly extends the public API for the Web SDK.

tests/languages/deno/tests.ts (2)

12-13: LGTM! Alias declarations follow established pattern.

The Operator and Condition aliases are correctly positioned with other helper aliases.


244-270: No issues found—test method names and Condition enum values are correct.

Verification confirms all test calls at lines 244-270 match the generated Operator API:

  • All eight array methods (arrayAppend, arrayPrepend, arrayInsert, arrayRemove, arrayUnique, arrayIntersect, arrayDiff, arrayFilter) are defined in the template with matching signatures
  • Condition.Equal enum value exists and is properly used in the arrayFilter call at line 263
tests/languages/android/Tests.kt (2)

11-12: LGTM! Imports added correctly.

The new imports for Operator and Condition are properly structured and consistent with the existing import pattern.


272-298: Test pattern is correct and consistent with codebase conventions.

The Operator tests follow the established pattern in the file for helper methods. Operator is a builder class from the io.appwrite dependency that returns serializable objects (similar to the Query helper tests), not service calls that throw exceptions. The test approach of writing output to file for verification, without try-catch blocks, is consistent with other helper method tests in the same file and is appropriate for Kotlin's unchecked exception model.

Copy link
Contributor

@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: 2

🧹 Nitpick comments (4)
templates/dotnet/Package/Operator.cs.twig (1)

12-25: Consider removing redundant EnumMember attributes.

The Condition enum has EnumMember attributes (lines 12-25), but the ToValue extension method uses a manual switch expression to map enum values to strings (lines 32-42). Since the switch statement explicitly handles the conversion, the EnumMember attributes are redundant and not used anywhere.

You can either:

  1. Remove the EnumMember attributes and keep the manual switch (simpler, current approach works fine), or
  2. Remove the manual switch and rely on a serialization-based approach using the EnumMember attributes

Also applies to: 30-43

templates/go/operator.go.twig (3)

25-35: Default to empty array when Values is absent (avoid "values": null).

Guard against accidental nil by initializing data.Values to [] if options.Values is nil. This keeps the JSON shape stable even if a future call site passes no values.

 func parseOperator(options operatorOptions) string {
   data := struct {
     Method string        `json:"method"`
     Values []interface{} `json:"values"`
   }{
     Method: options.Method,
   }
 
-  if options.Values != nil {
-    data.Values = *options.Values
-  }
+  if options.Values != nil {
+    data.Values = *options.Values
+  } else {
+    data.Values = []interface{}{}
+  }
 
   jsonData, err := json.Marshal(data)

108-114: Normalize nil input slices to [] to prevent "values": null.

Public APIs accepting []interface{} can receive nil; with the current flow that serializes as null. Normalize to empty slice for consistent wire format.

 func ArrayAppend(values []interface{}) string {
+  if values == nil {
+    values = []interface{}{}
+  }
   return parseOperator(operatorOptions{
     Method: "arrayAppend",
     Values: &values,
   })
 }
 
 func ArrayPrepend(values []interface{}) string {
+  if values == nil {
+    values = []interface{}{}
+  }
   return parseOperator(operatorOptions{
     Method: "arrayPrepend",
     Values: &values,
   })
 }
 
 func ArrayIntersect(values []interface{}) string {
+  if values == nil {
+    values = []interface{}{}
+  }
   return parseOperator(operatorOptions{
     Method: "arrayIntersect",
     Values: &values,
   })
 }
 
 func ArrayDiff(values []interface{}) string {
+  if values == nil {
+    values = []interface{}{}
+  }
   return parseOperator(operatorOptions{
     Method: "arrayDiff",
     Values: &values,
   })
 }

Also applies to: 115-121, 146-152, 153-159


8-18: Add brief GoDoc comments for exported API.

Consider 1‑liners for Condition and each exported function to satisfy GoDoc/lint and improve SDK discoverability.

Also applies to: 45-217

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f23cb97 and 611e8b2.

📒 Files selected for processing (3)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • tests/Base.php (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/Base.php
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (18)
  • GitHub Check: cli (console)
  • GitHub Check: dotnet (server)
  • GitHub Check: apple (client)
  • GitHub Check: react-native (client)
  • GitHub Check: build (8.3, Ruby27)
  • GitHub Check: build (8.3, Swift56)
  • GitHub Check: build (8.3, Python39)
  • GitHub Check: build (8.3, WebChromium)
  • GitHub Check: build (8.3, Ruby30)
  • GitHub Check: build (8.3, Python310)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, PHP83)
  • GitHub Check: build (8.3, Node18)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: build (8.3, FlutterBeta)
🔇 Additional comments (3)
templates/dotnet/Package/Operator.cs.twig (1)

76-79: Dependency verified — no issues found.

The Client.SerializerOptions reference in the ToString() method is valid. The Client class (defined in Client.cs.twig) contains a public static property SerializerOptions of type JsonSerializerOptions that is properly initialized with appropriate serialization settings including custom converters for JSON serialization.

templates/go/operator.go.twig (2)

28-28: Good: consistent JSON shape and fail‑fast marshaling.

Dropping omitempty on values and panicking on marshal failure resolves prior parity and silent‑error concerns. Looks solid.

Also applies to: 37-41


160-169: ArrayFilter parity: always emit two elements.

Initializing with [condition, nil] and overwriting when provided matches the expected ["<condition>", null] shape. Good fix.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
templates/swift/Sources/Operator.swift.twig (1)

236-242: arrayFilter still omits null placeholder when value is not provided.

The past review flagged that arrayFilter should emit an explicit null as the second element when value is omitted to maintain cross-SDK consistency. The current implementation only includes the condition when value is nil, resulting in a single-element values array instead of a two-element array with a null placeholder.

Based on past review feedback, consider this change:

 public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
     var values: [Any] = [condition.rawValue]
-    if let value = value {
-        values.append(value)
-    }
+    values.append(value ?? NSNull())
     return Operator(method: "arrayFilter", values: values).description
 }

This ensures the serialized JSON always contains two elements in the values array, matching the expected format across other SDK implementations.

🧹 Nitpick comments (2)
templates/swift/Sources/Operator.swift.twig (1)

156-162: Consider logging encoding failures.

The description property silently returns an empty string when JSON encoding fails, which may hide errors during development or debugging.

You could optionally add logging or return a fallback that indicates an error occurred:

 public var description: String {
     guard let data = try? JSONEncoder().encode(self) else {
+        print("Warning: Failed to encode Operator to JSON")
         return ""
     }
     
     return String(data: data, encoding: .utf8) ?? ""
 }
tests/languages/apple/Tests.swift (1)

251-277: Consider testing arrayFilter without the value parameter.

The tests cover all Operator methods, but line 270 only tests arrayFilter with a value provided. Given the discussion around null placeholder handling when the value is omitted, adding a test case like print(Operator.arrayFilter(Condition.equal)) would help verify the output format in that scenario.

Optionally add after line 270:

print(Operator.arrayFilter(Condition.equal))
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 611e8b2 and c734f3a.

📒 Files selected for processing (6)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/ruby/lib/container.rb.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • tests/languages/apple/Tests.swift (1 hunks)
  • tests/languages/dotnet/Tests.cs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • templates/ruby/lib/container/operator.rb.twig
  • tests/languages/dotnet/Tests.cs
  • templates/php/src/Operator.php.twig
🔇 Additional comments (9)
templates/swift/Sources/Operator.swift.twig (8)

3-11: LGTM!

The Condition enum is well-structured with clear, descriptive cases for comparison operations.


13-20: LGTM!

The OperatorValue enum now includes the .null case, addressing the past review concern about representing JSON nulls.


21-42: LGTM!

Decoding logic correctly handles null values (lines 24-25) and provides appropriate fallback error handling.


44-61: LGTM!

Encoding logic is complete with all cases covered, including .null encoding to JSON null (lines 57-58).


63-140: LGTM!

The Operator struct and convertToOperatorValueArray method correctly handle all input types, including preserving empty arrays (lines 111-113) and mapping unknown types to .null (lines 130-133), addressing past review concerns.


164-206: LGTM!

The arithmetic operators follow a consistent pattern with appropriate optional max/min parameters.


208-234: LGTM!

Array operators follow a consistent pattern and handle their parameters appropriately.


244-266: LGTM!

String, boolean, and date operators are well-implemented with clear, descriptive names and appropriate parameters.

templates/ruby/lib/container.rb.twig (1)

14-14: LGTM. Operator module properly integrated and tested.

The operator template exists at templates/ruby/lib/container/operator.rb.twig and is comprehensively tested in tests/languages/ruby/tests.rb with coverage for increment, decrement, arithmetic operations, array operations, string manipulation, and date operations. The require statement follows the correct pattern and integrates the module appropriately into the SDK initialization.

Copy link
Contributor

@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: 3

♻️ Duplicate comments (4)
templates/dotnet/Package/Operator.cs.twig (2)

115-123: Add division by zero validation.

The Divide method does not validate that divisor is non-zero. If zero is passed, the operation will fail at runtime when the server or client evaluates this operator.

Apply this diff to add validation:

 public static string Divide(double divisor, double? min = null)
 {
+    if (divisor == 0)
+    {
+        throw new ArgumentException("Divisor cannot be zero", nameof(divisor));
+    }
     var values = new List<object> { divisor };
     if (min.HasValue)
     {
         values.Add(min.Value);
     }
     return new Operator("divide", values).ToString();
 }

125-128: Add modulo by zero validation.

The Modulo method does not validate that divisor is non-zero, which will cause a runtime exception when evaluated.

Apply this diff to add validation:

 public static string Modulo(double divisor)
 {
+    if (divisor == 0)
+    {
+        throw new ArgumentException("Divisor cannot be zero", nameof(divisor));
+    }
     return new Operator("modulo", new List<object> { divisor }).ToString();
 }
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

60-92: Critical: Method naming mismatch with test expectations persists.

The array operator methods still use the "array" prefix (arrayAppend, arrayPrepend, arrayInsert, arrayRemove, arrayUnique, arrayIntersect, arrayDiff, arrayFilter), but the test file tests/languages/kotlin/Tests.kt calls these methods without the prefix (Operator.append, Operator.prepend, etc.). This mismatch will cause compilation failures.

Both the method names and the operator name strings (first argument to Operator(...)) need to be updated to remove the prefix for consistency with test expectations and other language implementations.

Apply this diff to fix the naming mismatch:

-        fun arrayAppend(values: List<Any>): String {
-            return Operator("arrayAppend", values).toJson()
+        fun append(values: List<Any>): String {
+            return Operator("append", values).toJson()
         }
 
-        fun arrayPrepend(values: List<Any>): String {
-            return Operator("arrayPrepend", values).toJson()
+        fun prepend(values: List<Any>): String {
+            return Operator("prepend", values).toJson()
         }
 
-        fun arrayInsert(index: Int, value: Any): String {
-            return Operator("arrayInsert", listOf(index, value)).toJson()
+        fun insert(index: Int, value: Any): String {
+            return Operator("insert", listOf(index, value)).toJson()
         }
 
-        fun arrayRemove(value: Any): String {
-            return Operator("arrayRemove", listOf(value)).toJson()
+        fun remove(value: Any): String {
+            return Operator("remove", listOf(value)).toJson()
         }
 
-        fun arrayUnique(): String {
-            return Operator("arrayUnique", emptyList()).toJson()
+        fun unique(): String {
+            return Operator("unique", emptyList()).toJson()
         }
 
-        fun arrayIntersect(values: List<Any>): String {
-            return Operator("arrayIntersect", values).toJson()
+        fun intersect(values: List<Any>): String {
+            return Operator("intersect", values).toJson()
         }
 
-        fun arrayDiff(values: List<Any>): String {
-            return Operator("arrayDiff", values).toJson()
+        fun diff(values: List<Any>): String {
+            return Operator("diff", values).toJson()
         }
 
-        fun arrayFilter(condition: Condition, value: Any? = null): String {
+        fun filter(condition: Condition, value: Any? = null): String {
             val values = mutableListOf<Any>(condition.value)
             value?.let { values.add(it) }
-            return Operator("arrayFilter", values).toJson()
+            return Operator("filter", values).toJson()
         }
templates/swift/Sources/Operator.swift.twig (1)

238-244: arrayFilter should always include two elements to match other SDKs.

The current implementation conditionally appends the value, resulting in a single-element values array when value is nil. According to the past review comment, this should emit an explicit null as the second element to maintain consistency across SDKs.

Based on learnings

Apply this diff to ensure arrayFilter always has two elements:

 public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
-    var values: [Any] = [condition.rawValue]
-    if let value = value {
-        values.append(value)
-    }
-    return Operator(method: "arrayFilter", values: values).description
+    let placeholder: Any = value ?? NSNull()
+    return Operator(method: "arrayFilter", values: [condition.rawValue, placeholder]).description
 }
🧹 Nitpick comments (9)
templates/swift/Sources/Operator.swift.twig (1)

158-164: Consider logging encoding failures in description.

The description property silently returns an empty string when JSON encoding fails. While this prevents crashes, it might hide underlying issues during development or debugging. Consider whether logging a warning would be beneficial for troubleshooting.

templates/dart/lib/operator.dart.twig (1)

34-34: Minor style: Add space after if keyword.

Dart style guidelines recommend a space between the if keyword and opening parenthesis.

Apply this diff:

-    if(values != null) {
+    if (values != null) {
templates/deno/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for consistency.

While OperatorValuesList and OperatorValues are exported, OperatorValuesSingle is not. For API consistency and potential external usage, consider exporting all type aliases.

Apply this diff:

-type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesSingle = string | number | boolean;
templates/node/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for consistency.

Same observation as the Deno version - consider exporting OperatorValuesSingle to match the export pattern of the other type aliases.

Apply this diff:

-type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesSingle = string | number | boolean;
templates/react-native/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for consistency.

Same pattern across all TypeScript implementations - OperatorValuesSingle could be exported for consistency.

Apply this diff:

-type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesSingle = string | number | boolean;
templates/web/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for consistency.

Final TypeScript file with the same export consistency opportunity.

Apply this diff:

-type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesSingle = string | number | boolean;
templates/php/src/Operator.php.twig (2)

34-37: Consider error handling for json_encode.

The json_encode() call on line 36 can return false on failure. While unlikely with these simple structures, consider whether error handling or a fallback is needed for robustness.

If error handling is desired, consider:

 public function __toString(): string
 {
-    return json_encode($this);
+    $json = json_encode($this);
+    if ($json === false) {
+        throw new \RuntimeException('Failed to encode Operator: ' . json_last_error_msg());
+    }
+    return $json;
 }

223-230: Consider validating the condition parameter.

The arrayFilter() method accepts a string $condition but doesn't validate that it's one of the Condition class constants. Depending on your validation strategy, you might want to add a check.

Example validation:

 public static function arrayFilter(string $condition, mixed $value = null): string
 {
+    $validConditions = [
+        Condition::Equal, Condition::NotEqual, Condition::GreaterThan,
+        Condition::GreaterThanEqual, Condition::LessThan, Condition::LessThanEqual,
+        Condition::Contains, Condition::IsNull, Condition::IsNotNull
+    ];
+    if (!in_array($condition, $validConditions, true)) {
+        throw new \InvalidArgumentException('Invalid condition: ' . $condition);
+    }
     $values = [$condition];
     if ($value !== null) {
         $values[] = $value;
     }
     return (new Operator('arrayFilter', $values))->__toString();
 }
templates/ruby/lib/container/operator.rb.twig (1)

39-39: Prefer idiomatic class << self for singleton methods.

Using class << Operator works but is unconventional. The Ruby community standard is class << self when defining singleton methods inside a class.

Apply this diff:

-        class << Operator
+        class << self
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8df4a60 and ed20156.

📒 Files selected for processing (13)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • templates/python/package/operator.py.twig
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, Ruby30)
  • GitHub Check: build (8.3, DotNet90)
  • GitHub Check: build (8.3, DartStable)
  • GitHub Check: build (8.3, CLINode18)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, CLINode16)
  • GitHub Check: swift (server)
  • GitHub Check: kotlin (server)
  • GitHub Check: apple (client)
  • GitHub Check: android (client)
🔇 Additional comments (23)
templates/swift/Sources/Operator.swift.twig (6)

3-13: LGTM!

The Condition enum is well-structured with appropriate String raw values and Codable conformance. The inclusion of isNull and isNotNull cases extends the condition set appropriately.


15-63: LGTM!

The OperatorValue enum implementation is comprehensive and correctly addresses all past review comments:

  • Includes the .null case for representing JSON nulls
  • Properly decodes explicit nulls via container.decodeNil()
  • Correctly encodes .null to JSON null via container.encodeNil()
  • Supports nested arrays through recursive [OperatorValue] case

81-142: LGTM!

The convertToOperatorValueArray method properly addresses the past review comment about preserving empty arrays and mapping unknowns to .null:

  • Empty arrays are preserved rather than being dropped (lines 113-115)
  • Uses map instead of compactMap to retain all items (line 118)
  • NSNull and unknown types are converted to .null (lines 119-120, 132-134)
  • Nested empty arrays are preserved via the ?? [] fallback (line 130)

166-208: LGTM!

The arithmetic operator factory methods follow a consistent and correct pattern:

  • Required parameters are always included
  • Optional bounds (max/min) are conditionally appended only when provided
  • Use of Double for numeric values is appropriate for arithmetic operations

210-237: LGTM!

The array manipulation factory methods are well-implemented:

  • arrayInsert appropriately uses Int for the index parameter
  • arrayUnique correctly uses an empty values array
  • All methods follow consistent patterns

246-268: LGTM!

The string and date operator factory methods are correctly implemented:

  • replace properly accepts both search and replace parameters
  • toggle and dateSetNow correctly use empty values arrays
  • Date methods appropriately use Int for day counts
templates/dart/lib/operator.dart.twig (1)

1-153: Implementation looks solid.

The Dart operator builder correctly implements the Condition enum and Operator class with proper JSON serialization. The private constructor pattern and factory methods provide a clean API surface. All operations correctly handle optional parameters and serialize to the expected JSON format.

templates/deno/src/operator.ts.twig (1)

1-271: LGTM - Clean TypeScript implementation.

The Deno operator builder is well-structured with proper type definitions, enum, and comprehensive factory methods. JSON serialization logic correctly handles both single values and arrays. All operator methods properly construct their values arrays and delegate to the Operator constructor.

templates/node/src/operator.ts.twig (1)

1-271: LGTM - Implementation matches Deno version.

The Node operator builder correctly implements the same pattern as the Deno version, providing consistent operator JSON generation across platforms.

templates/react-native/src/operator.ts.twig (1)

1-271: LGTM - Consistent with other TypeScript implementations.

The React Native operator builder maintains the same clean structure and correctness as the Node and Deno versions.

templates/web/src/operator.ts.twig (1)

1-271: LGTM - Web implementation mirrors other TypeScript versions.

The Web operator builder is correctly implemented with the same comprehensive operator methods and proper JSON serialization.

templates/go/operator.go.twig (1)

1-219: LGTM - All previous review concerns addressed.

The Go operator implementation correctly handles JSON serialization with proper error handling (panic on marshal failure). All operator functions properly construct their values slices and delegate to parseOperator. The implementation is consistent with the operator patterns in other languages.

Previous review comments have been successfully addressed:

  • No unused toArray function
  • Marshal errors now handled with panic
  • omitempty removed from values JSON tag (line 30)
  • ArrayFilter always emits 2-element array with nil default (lines 163-166)
templates/php/src/Operator.php.twig (5)

5-16: LGTM! Clean constant definitions.

The Condition class provides a clear set of comparison operations with consistent naming.


18-32: LGTM! Well-structured constructor with sensible value normalization.

The constructor appropriately handles both array and scalar inputs by normalizing them into the internal array representation.


232-263: LGTM! String and boolean operations are well-structured.

The concat(), replace(), and toggle() methods follow the established pattern correctly.


265-295: LGTM! Date operations follow the established pattern.

The date manipulation methods are implemented consistently with the rest of the class.


103-110: ****

The divide() method is a JSON serializer in an SDK code generator, not a mathematical operation. It only builds operation payloads like {"method": "divide", "values": [2]} for server processing. Validation should occur server-side where the actual division executes, not in the client SDK. This design is consistent with all other arithmetic operations in the class (increment, decrement, multiply, power), which similarly lack parameter validation by design.

Likely an incorrect or invalid review comment.

templates/ruby/lib/container/operator.rb.twig (6)

1-14: LGTM!

The JSON import and Condition module constants are well-structured and follow Ruby naming conventions.


16-37: LGTM!

The Operator class initialization and serialization logic correctly handles optional values and conditionally includes the values key in JSON output.


102-106: Great fix from previous review!

The array_filter method now correctly omits the optional value parameter when not provided, aligning with the pattern used in other methods.


40-89: LGTM!

The arithmetic and array operation methods correctly implement conditional parameter inclusion, ensuring optional parameters are only added to the values array when provided.


108-130: LGTM!

The string and date manipulation methods are correctly implemented with appropriate parameter handling.


90-92: The review comment's premise about array_filter is incorrect and should be reconsidered.

Based on code inspection across all language templates:

  1. array_filter does NOT pass nil - The review claims it was "fixed to omit optional parameters entirely (passing nil instead)," but the actual implementation shows it builds and passes a values array (either [condition] or [condition, value]), never nil.

  2. All parameterless operations consistently pass empty arrays - array_unique(), toggle(), and date_set_now() all pass [] to Operator.new() across Ruby, Python, and TypeScript identically.

  3. Operator serialization is consistent - The Operator class only omits the values key from JSON when values is nil/undefined. Passing [] results in "values":[] in the output. Without API documentation specifying the expected format, both approaches appear valid.

Given that all implementations are consistent across 13+ language templates and the review's factual claim about array_filter is unsupported, further action depends on whether you have API specifications defining the expected JSON output format for these operations.

Copy link
Contributor

@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: 1

🧹 Nitpick comments (5)
templates/react-native/src/operator.ts.twig (3)

1-15: Well-defined types and enum.

The Condition enum and type definitions are correctly implemented. However, OperatorValuesSingle is not exported while OperatorValuesList and OperatorValues are, creating an inconsistent API surface.

Consider exporting OperatorValuesSingle for API consistency:

-type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesSingle = string | number | boolean;

20-55: Constructor and serialization logic are correct.

The value normalization in the constructor properly handles both array and non-array inputs, and the JSON serialization is straightforward and accurate.

Consider making the values property private since it's only used internally:

 export class Operator {
   method: string;
-  values: OperatorValuesList | undefined;
+  private values: OperatorValuesList | undefined;

64-139: Arithmetic operators follow a consistent pattern.

All arithmetic factory methods are well-implemented and consistent. However, divide and modulo operations don't validate that the divisor is non-zero, which could lead to runtime errors if not handled by the backend.

Add client-side validation for division operations:

 static divide = (divisor: number, min?: number): string => {
+  if (divisor === 0) {
+    throw new Error("Divisor cannot be zero");
+  }
   const values: any[] = [divisor];
   if (min !== undefined) {
     values.push(min);
   }
   return new Operator("divide", values).toString();
 };
 static modulo = (divisor: number): string => {
+  if (divisor === 0) {
+    throw new Error("Divisor cannot be zero");
+  }
   return new Operator("modulo", [divisor]).toString();
+ };
templates/php/src/Operator.php.twig (2)

171-174: Consider validating array index bounds.

The arrayInsert() method accepts any integer index without validation. If the backend doesn't handle negative or out-of-bounds indices gracefully, consider adding validation here.

If validation is needed, you could add a check like:

 public static function arrayInsert(int $index, mixed $value): string
 {
+    if ($index < 0) {
+        throw new \InvalidArgumentException('Index cannot be negative');
+    }
     return (new Operator('arrayInsert', [$index, $value]))->__toString();
 }

226-233: Consider validating the condition parameter.

The arrayFilter() method accepts any string for $condition without validating it against the Condition class constants. This could lead to runtime errors on the backend if an invalid condition is passed.

If you want stricter validation, you could add a check:

 public static function arrayFilter(string $condition, mixed $value = null): string
 {
+    $validConditions = [
+        Condition::Equal, Condition::NotEqual, Condition::GreaterThan,
+        Condition::GreaterThanEqual, Condition::LessThan, Condition::LessThanEqual,
+        Condition::Contains, Condition::IsNull, Condition::IsNotNull
+    ];
+    if (!in_array($condition, $validConditions, true)) {
+        throw new \InvalidArgumentException("Invalid condition: {$condition}");
+    }
     $values = [$condition];
     if ($value !== null) {
         $values[] = $value;
     }
     return (new Operator('arrayFilter', $values))->__toString();
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed20156 and 3c4dc84.

📒 Files selected for processing (6)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • templates/node/src/operator.ts.twig
  • templates/deno/src/operator.ts.twig
  • templates/web/src/operator.ts.twig
  • templates/dotnet/Package/Operator.cs.twig
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (16)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, Python313)
  • GitHub Check: build (8.3, WebChromium)
  • GitHub Check: build (8.3, Python312)
  • GitHub Check: build (8.3, Ruby31)
  • GitHub Check: build (8.3, Ruby27)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, PHP80)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, CLINode18)
  • GitHub Check: build (8.3, DotNet60)
  • GitHub Check: build (8.3, DotNet80)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: apple (client)
  • GitHub Check: swift (server)
  • GitHub Check: android (client)
🔇 Additional comments (5)
templates/react-native/src/operator.ts.twig (1)

147-270: Array, string, boolean, and date operators are correctly implemented.

All factory methods consistently follow the established pattern, properly handle parameters, and generate correct JSON descriptors. The arrayFilter method appropriately converts the Condition enum to a string value.

templates/php/src/Operator.php.twig (4)

5-16: LGTM! Clean constant definitions.

The Condition class provides a clear set of comparison operation constants with consistent naming.


18-46: LGTM! Well-structured JsonSerializable implementation.

The Operator class properly implements JsonSerializable with good value normalization in the constructor and clean serialization logic.


118-124: LGTM! Zero divisor validation properly implemented.

The modulo() method now correctly validates for zero divisor with clear error messaging. This addresses the previous review comment.


48-62: LGTM! Consistent factory method pattern.

The static factory methods follow a consistent, clear pattern:

  • Proper PHPDoc annotations
  • Type hints for parameters and return types
  • Conditional handling of optional parameters
  • Clean delegation to the Operator constructor

Also applies to: 64-78, 80-94, 126-140, 142-151, 153-162, 176-185, 187-195, 197-206, 208-217, 235-244, 246-256, 258-266, 268-277, 279-288, 290-298

Copy link
Contributor

@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: 4

♻️ Duplicate comments (3)
templates/dotnet/Package/Operator.cs.twig (1)

117-125: Add division by zero validation.

The Divide method still lacks validation for divisor == 0, which was flagged in a previous review. This is inconsistent with the Modulo method (lines 129-132) which correctly validates for zero. Without this check, the method will produce an invalid operator that will fail when evaluated.

Apply this diff to add validation:

 public static string Divide(double divisor, double? min = null)
 {
+    if (divisor == 0)
+    {
+        throw new ArgumentException("Divisor cannot be zero", nameof(divisor));
+    }
     var values = new List<object> { divisor };
     if (min.HasValue)
     {
         values.Add(min.Value);
     }
     return new Operator("divide", values).ToString();
 }
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

61-93: Method naming vs tests (array-prefixed vs unprefixed) — please confirm

Previous review flagged tests calling append/prepend/etc. while template defines arrayAppend/arrayPrepend/etc. Validate current tests and align names or test calls.

#!/bin/bash
# Compare method names in Android/Kotlin templates vs Kotlin tests
echo "Template methods:"
rg -n 'fun (array)?(append|prepend|insert|remove|unique|intersect|diff|filter)\(' templates/android/ templates/kotlin/
echo
echo "Test calls:"
rg -n 'Operator\.(array)?(append|prepend|insert|remove|unique|intersect|diff|filter)\(' tests/ 2>/dev/null || true
templates/swift/Sources/Operator.swift.twig (1)

239-245: arrayFilter should include explicit null placeholder

Ensure second element is present when value is nil to match other SDKs.

-    public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
-        var values: [Any] = [condition.rawValue]
-        if let value = value {
-            values.append(value)
-        }
-        return Operator(method: "arrayFilter", values: values).description
-    }
+    public static func arrayFilter(_ condition: Condition, value: Any? = nil) -> String {
+        return Operator(method: "arrayFilter", values: [condition.rawValue, value ?? NSNull()]).description
+    }
🧹 Nitpick comments (9)
templates/ruby/lib/container/operator.rb.twig (5)

16-27: Consider using .nil? for consistency.

The initialization logic is correct. However, for Ruby style consistency, consider using .nil? instead of != nil (line 20), which aligns with line 31 and is the more idiomatic Ruby pattern.

Optional refactor:

-            if values != nil
+            if !values.nil?
                 if values.is_a?(Array)

Note: You may also want to apply this pattern to lines 42, 48, 54, 60, 71, and 105 for consistency throughout the file.


35-37: Minor: self. is unnecessary when calling instance methods.

The delegation to to_json works correctly, but self. is not needed in Ruby when calling instance methods on the current object.

Optional refactor:

         def to_s
-            return self.to_json
+            return to_json
         end

39-39: Consider using class << self for defining class methods.

While class << Operator is valid Ruby, the more idiomatic pattern is class << self when defining class methods inside a class definition.

Optional refactor:

-        class << Operator
+        class << self

64-67: Redundant zero check in modulo.

The condition divisor == 0 || divisor == 0.0 is redundant because in Ruby, 0 == 0.0 evaluates to true. A single check suffices.

Optional refactor:

             def modulo(divisor)
-                raise ArgumentError, "Divisor cannot be zero" if divisor == 0 || divisor == 0.0
+                raise ArgumentError, "Divisor cannot be zero" if divisor == 0
                 return Operator.new("modulo", [divisor]).to_s
             end

75-131: LGTM!

The array, string, and date operator methods are well-implemented:

  • Array operations correctly handle their respective inputs
  • String operations (concat, replace, toggle) are straightforward
  • Date operations provide the expected functionality

Minor nitpick: Methods with no parameters (array_unique, toggle, date_set_now) could omit empty parentheses for more idiomatic Ruby style, but this is purely cosmetic.

templates/dotnet/Package/Operator.cs.twig (1)

212-215: Consider adding null validation for string parameters.

The Replace method accepts search and replace string parameters without null checks. While the server will handle null values, adding validation would provide better error messages and fail-fast behavior, consistent with the list parameter validation added elsewhere in this class.

Apply this diff to add validation:

 public static string Replace(string search, string replace)
 {
+    if (search == null)
+    {
+        throw new ArgumentNullException(nameof(search));
+    }
+    if (replace == null)
+    {
+        throw new ArgumentNullException(nameof(replace));
+    }
     return new Operator("replace", new List<object> { search, replace }).ToString();
 }
templates/react-native/src/operator.ts.twig (1)

1-3: Simplify OperatorValuesList; any[] subsumes specific array unions

Removes redundancy; keeps API unchanged.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = any[];
 export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
templates/node/src/operator.ts.twig (1)

1-3: Collapse OperatorValuesList to any[]

Type union is redundant; any[] already covers it.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = any[];
 export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
templates/web/src/operator.ts.twig (1)

1-3: Consider stronger typing for array values.

The any[] type in OperatorValuesList reduces type safety. While this provides flexibility, it allows any array type to be passed. Consider whether the current typing is sufficient for your use case or if stricter constraints would catch more errors at compile time.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c4dc84 and c26f8d6.

📒 Files selected for processing (13)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
  • tests/languages/web/index.html (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • templates/go/operator.go.twig
  • templates/python/package/operator.py.twig
  • templates/dart/lib/operator.dart.twig
  • templates/deno/src/operator.ts.twig
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: go (server)
  • GitHub Check: build (8.3, Node20)
  • GitHub Check: react-native (client)
  • GitHub Check: node (server)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, Python310)
  • GitHub Check: build (8.3, Python311)
  • GitHub Check: build (8.3, WebNode)
  • GitHub Check: apple (client)
  • GitHub Check: android (client)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: web (client)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, Android5Java17)
🔇 Additional comments (13)
templates/ruby/lib/container/operator.rb.twig (3)

3-14: LGTM!

The module structure and Condition constants are well-defined and follow Ruby naming conventions.


40-73: LGTM!

The arithmetic operator methods (increment, decrement, multiply, divide, power) correctly handle optional parameters and build the appropriate value arrays. The defensive check in modulo for zero division is good practice.


103-107: ✅ Previous issue resolved.

The array_filter method now correctly omits the value parameter when it's nil, addressing the concern raised in the previous review.

templates/dotnet/Package/Operator.cs.twig (4)

10-50: LGTM! Previous critical issue resolved.

The Condition enum and ConditionExtensions.ToValue() method are now complete. All nine enum members, including IsNull and IsNotNull, are properly defined and handled in the switch expression. The previous critical issue has been successfully addressed.


52-85: LGTM! Clean implementation of Operator class structure.

The class properties, constructors, and serialization logic are well-implemented. The constructor correctly handles both IList collections and single values, and the ToString() method uses Client.SerializerOptions for consistent JSON serialization.


146-205: LGTM! Array operator methods properly implement null validation.

All array methods that accept List<object> parameters now correctly validate for null and throw ArgumentNullException. The ArrayFilter method properly uses condition.ToValue() to serialize the enum. The previous major issues have been successfully addressed.


217-235: LGTM! Date and toggle operators are correctly implemented.

The Toggle, DateAddDays, DateSubDays, and DateSetNow methods are properly implemented with appropriate parameter types and no unnecessary validation.

templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

19-29: Review comment is incorrect—proposed changes won't achieve stated goal

The suggestion to change List<Any> to List<Any?> and use listOf(condition.value, value) won't create the claimed "placeholder" behavior. The GSON configuration in JsonExtensions.kt.twig does not call .serializeNulls(), meaning GSON strips null values during serialization. Thus listOf(condition.value, null) serializes identically to the current conditional-add approach—both produce [condition.value] in JSON. The type annotation alone doesn't control serialization behavior.

To actually preserve null placeholders in JSON output, JsonExtensions.kt.twig would need .serializeNulls() added to the GsonBuilder. Until then, the current pattern is correct and the proposed changes are cosmetic without the claimed "parity" benefit.

Likely an incorrect or invalid review comment.

templates/web/src/operator.ts.twig (3)

5-15: LGTM!

The Condition enum is well-defined with appropriate comparison and null-check operators for filtering operations.


20-55: LGTM!

The Operator class structure is clean and the constructor correctly normalizes single values to arrays. The toString() method appropriately serializes to JSON format.


145-275: LGTM!

The array, string, boolean, and date operation methods are well-implemented with consistent patterns. The arrayFilter method correctly handles the Condition enum, and all methods appropriately construct and serialize operators.

tests/languages/web/index.html (2)

24-24: LGTM!

The destructuring correctly includes Operator and Condition to support the new operator helper tests.


320-346: LGTM!

The operator helper tests comprehensively cover all operator methods including arithmetic operations, array manipulations, string operations, boolean toggles, and date operations. The test cases include both simple and complex parameter scenarios.

Copy link
Contributor

@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: 2

♻️ Duplicate comments (4)
templates/react-native/src/operator.ts.twig (1)

218-224: arrayFilter should emit explicit null for cross-SDK parity when value omitted.

The current implementation conditionally appends the value, resulting in ["condition"] when value is undefined, rather than ["condition", null]. This creates inconsistency with other SDKs (e.g., Go) that always emit a two-element array.

templates/android/library/src/main/java/io/package/Operator.kt.twig (2)

90-93: arrayFilter should emit explicit null placeholder for cross-SDK parity.

The current implementation conditionally appends the value, resulting in ["condition"] when value is null. For consistency with the Go implementation (templates/go/operator.go.twig lines 183-187), consider always emitting ["condition", null].


62-94: Method naming mismatch with test expectations.

The methods use an "array" prefix (arrayAppend, arrayPrepend, etc.), but past review comments indicate tests call these methods without the prefix (append, prepend, etc.). This mismatch will cause compilation failures.

templates/node/src/operator.ts.twig (1)

218-224: arrayFilter still needs null placeholder for consistency.

The previously flagged issue remains unresolved. The arrayFilter method should always emit a two-element array with null as the second element when no value is provided, for consistency with other SDKs and test expectations.

Apply this diff as previously suggested:

  static arrayFilter = (condition: Condition, value?: any): string => {
-   const values: any[] = [condition as string];
-   if (value !== undefined) {
-     values.push(value);
-   }
-   return new Operator("arrayFilter", values).toString();
+   return new Operator("arrayFilter", [condition as string, value ?? null]).toString();
  };
🧹 Nitpick comments (2)
templates/react-native/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for API consistency.

OperatorValuesSingle (line 1) is not exported while OperatorValuesList and OperatorValues (lines 2-3) are. If consumers need to reference the single-value type directly, consider adding the export keyword.

templates/deno/src/operator.ts.twig (1)

1-3: Consider exporting OperatorValuesSingle for API consistency.

OperatorValuesSingle is not exported while OperatorValuesList and OperatorValues are. Exporting all related type aliases provides a more consistent public API surface.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c26f8d6 and c4af38b.

📒 Files selected for processing (13)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • templates/dotnet/Package/Operator.cs.twig
  • templates/php/src/Operator.php.twig
🔇 Additional comments (31)
templates/python/package/operator.py.twig (2)

18-29: LGTM! Conditional attribute initialization allows clean JSON omission.

The __init__ method only sets self.values when values is not None, and __str__ uses self.__dict__ for serialization. This elegantly omits the "values" key from the JSON output when no values are provided, which is a valid design choice for this implementation.


103-107: Cross-SDK inconsistency confirmed; verify whether aligned implementations are intended.

The script output confirms the review comment's observation: Python, TypeScript, Ruby, and Deno all omit the second element when the optional value is not provided, producing ["condition"]. However, Go uniquely always initializes with two elements, producing ["condition", null] when value is omitted.

All non-Go SDKs (Python, TypeScript, Ruby, Deno) follow the same pattern—they only append the second element if it's explicitly provided. This consistency across Python, TypeScript, and Ruby suggests this behavior may be intentional, or that Go is the implementation that diverged and should be reconciled with the others.

The discrepancy warrants clarification: confirm whether Python should maintain consistency with TypeScript and Ruby, or whether all implementations should align with Go's always-present-null-as-second-element approach.

templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

19-29: LGTM! Null-safe type changes applied correctly.

The Operator class now uses List<Any?>? for the values parameter (line 21), and all factory methods construct mutableListOf<Any?> (e.g., line 27). This enables proper serialization of explicit null values.

templates/deno/src/operator.ts.twig (2)

1-55: LGTM! Well-structured Operator implementation.

The type definitions, Condition enum, and Operator class with JSON serialization are correctly implemented. The constructor properly normalizes scalar values to arrays, and the toString method provides clean JSON output.


218-224: arrayFilter should emit explicit null for cross-SDK parity when value omitted.

Similar to the React Native implementation, this produces ["condition"] when value is undefined, rather than ["condition", null]. For consistency across SDKs, consider always emitting a two-element array.

templates/ruby/lib/container/operator.rb.twig (3)

17-37: LGTM! Clean implementation with intentional nil handling.

The initialize method conditionally sets @values (lines 20-26), and to_json omits the :values key when nil (line 31). This is a valid design choice that produces cleaner JSON output for operations without values.


104-108: array_filter behavior differs from other SDKs but marked as addressed.

The current implementation produces ["condition"] when value is nil, rather than ["condition", null]. Past review comments indicate this was addressed in commit e6a0c1f, suggesting this behavior is intentional for Ruby, though it differs from the Go implementation.


58-63: LGTM! Proper zero-division validation.

The divide method (lines 58-63) correctly validates against both integer and float zero values before proceeding with the operation.

templates/swift/Sources/Operator.swift.twig (3)

15-63: LGTM! Comprehensive null handling implemented.

The OperatorValue enum now includes a null case (line 21), and the Codable implementation correctly decodes (lines 26-27) and encodes (lines 59-60) explicit null values. This enables proper cross-SDK null serialization.


81-142: LGTM! Robust array conversion with null preservation.

The convertToOperatorValueArray method now preserves empty arrays (lines 113-115), maps NSNull to .null (lines 119-120), and handles nested arrays without dropping elements (lines 129-131). Unknown types correctly map to .null (lines 132-134).


240-245: arrayFilter should emit explicit null placeholder when value is nil.

The current implementation produces ["condition"] when value is nil (line 244). For cross-SDK parity (see Go implementation at templates/go/operator.go.twig lines 183-187), consider always emitting ["condition", NSNull()] or similar to produce a two-element array.

templates/go/operator.go.twig (3)

27-45: LGTM! Proper error handling and JSON serialization.

The parseOperator function now correctly handles marshal errors with panic (lines 39-42), which is appropriate for template-generated code where marshaling failure indicates a programmer error. The Values field uses json:"values" without omitempty (line 30), ensuring empty arrays are always serialized.


183-192: LGTM! ArrayFilter correctly emits null placeholder for cross-SDK parity.

The implementation initializes the values slice with nil as the second element (line 184) and conditionally overwrites it when a value is provided (lines 185-186). This ensures the serialized output is always ["<condition>", null] or ["<condition>", <value>], maintaining consistency across SDKs.


80-100: LGTM! Comprehensive zero-division validation.

The Divide function properly validates against zero for both int and float64 types (lines 82-91), preventing runtime panics from division by zero.

templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (3)

19-60: LGTM! Null-safe Operator implementation.

The Operator class correctly uses List<Any?>? for the values parameter (line 21), and all factory methods construct mutableListOf<Any?> (e.g., line 27). This enables proper serialization of explicit null values while maintaining type safety.


90-93: Verify intended behavior: arrayFilter omits second element when value is null.

The current implementation produces ["condition"] when value is null, whereas the Go implementation (templates/go/operator.go.twig lines 183-187) always produces ["condition", null] for cross-SDK consistency. Consider aligning the behavior or documenting the intentional divergence.


44-49: LGTM! Proper zero-division validation.

The divide method correctly validates that the divisor is not zero (line 45) using require, which throws IllegalArgumentException if the condition fails. This prevents runtime division-by-zero errors.

templates/dart/lib/operator.dart.twig (5)

3-20: Clean enum implementation.

The Condition enum is well-structured with appropriate string values and toString override for serialization.


22-43: Solid implementation of the Operator class.

The private constructor pattern and JSON serialization logic are well-implemented and follow Dart best practices.


44-98: Excellent validation in arithmetic operations.

The divide and modulo methods correctly validate against zero divisors, and all arithmetic operations follow a consistent pattern with appropriate optional parameters.


101-127: Array operations are well-implemented.

The array manipulation methods follow a clean and consistent pattern.


137-160: String and date operations look good.

The concat, replace, toggle, and date manipulation methods are correctly implemented.

templates/web/src/operator.ts.twig (5)

1-15: Well-defined types and enum.

The type definitions and Condition enum are clean and appropriate for TypeScript.


17-55: Solid Operator class implementation.

The constructor's value normalization and JSON serialization are correctly implemented.


57-146: Arithmetic operations are correctly implemented.

The zero-divisor validation previously flagged for the divide method has been successfully addressed. Both divide and modulo now include appropriate validation.


148-217: Array operations are well-implemented.

The array manipulation methods are clean and follow consistent patterns.


226-277: String and date operations are correct.

The concat, replace, toggle, and date manipulation methods are well-implemented.

templates/node/src/operator.ts.twig (4)

1-55: Types, enum, and class structure are well-defined.

The TypeScript definitions and Operator class implementation are sound.


57-146: Arithmetic operations are correctly implemented.

All mathematical operations, including proper zero-divisor validation for divide and modulo, are well-implemented.


148-217: Array operations look good.

The array manipulation methods are clean and consistent.


226-277: String and date operations are well-implemented.

The concat, replace, toggle, and date methods are correct.

@abnegate abnegate requested a review from ChiragAgg5k October 23, 2025 10:35
# Conflicts:
#	tests/languages/web/index.html
Copy link
Contributor

@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: 1

🧹 Nitpick comments (19)
templates/deno/src/operator.ts.twig (3)

1-3: Simplify value types

The union includes any[], which subsumes the specific array types. Prefer a single unknown[] for clarity.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = unknown[];
 export type OperatorValues = OperatorValuesSingle | OperatorValuesList;

21-22: Make fields immutable

Prevent accidental mutation after construction.

-  method: string;
-  values: OperatorValuesList | undefined;
+  readonly method: string;
+  readonly values?: OperatorValuesList;

218-221: Tiny cleanup: drop redundant cast

Condition is a string enum; no need for as string.

-  static arrayFilter = (condition: Condition, value?: any): string => {
-    const values: any[] = [condition as string, value === undefined ? null : value];
+  static arrayFilter = (condition: Condition, value?: any): string => {
+    const values: any[] = [condition, value === undefined ? null : value];
     return new Operator("arrayFilter", values).toString();
   };
templates/react-native/src/operator.ts.twig (3)

1-3: Simplify value types

As with Deno, prefer unknown[] over a union that already includes any[].

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = unknown[];
 export type OperatorValues = OperatorValuesSingle | OperatorValuesList;

21-22: Make fields immutable

Use readonly to prevent accidental mutation.

-  method: string;
-  values: OperatorValuesList | undefined;
+  readonly method: string;
+  readonly values?: OperatorValuesList;

219-219: Drop redundant cast

Condition is already a string enum.

-    const values: any[] = [condition as string, value === undefined ? null : value];
+    const values: any[] = [condition, value === undefined ? null : value];
templates/ruby/lib/container/operator.rb.twig (2)

1-1: Optional: freeze string literals

Add the magic comment to reduce string allocations.

+ # frozen_string_literal: true
 require 'json'

58-68: Idiomatic zero checks

Minor style tweak:

-                raise ArgumentError, "Divisor cannot be zero" if divisor == 0 || divisor == 0.0
+                raise ArgumentError, "Divisor cannot be zero" if divisor.to_f.zero?
templates/swift/Sources/Operator.swift.twig (2)

191-206: Prefer throwing/precondition over fatalError for zero divisor

Crashing the process is harsh for a serialization helper. Consider throwing an error or using precondition to fail in debug only.

-        if divisor == 0 {
-            fatalError("Divisor cannot be zero")
-        }
+        precondition(divisor != 0, "Divisor cannot be zero")

Apply similarly in modulo().


158-164: Optional: reuse JSONEncoder

description creates a new JSONEncoder each call. Consider a static encoder to avoid repeated allocations.

private static let encoder = JSONEncoder()
// ...
guard let data = try? Operator.encoder.encode(self) else { ... }
templates/node/src/operator.ts.twig (3)

1-3: Tighten types; avoid redundant union.

any[] already subsumes the other array unions. Prefer a single, safer alias.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
-export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = any[]; // or readonly unknown[]
+export type OperatorValues = OperatorValuesSingle | OperatorValuesList;

21-43: Make Operator immutable.

Prevents accidental mutation after construction and improves predictability.

-export class Operator {
-  method: string;
-  values: OperatorValuesList | undefined;
+export class Operator {
+  readonly method: string;
+  readonly values: ReadonlyArray<unknown> | undefined;
@@
-    if (values !== undefined) {
-      if (Array.isArray(values)) {
-        this.values = values;
-      } else {
-        this.values = [values] as OperatorValuesList;
-      }
-    }
+    if (values !== undefined) {
+      const arr = Array.isArray(values) ? values : [values];
+      this.values = Object.freeze([...arr]);
+    }

218-221: Minor: drop unnecessary cast.

Condition is a string enum; the as string is redundant.

-  static arrayFilter = (condition: Condition, value?: any): string => {
-    const values: any[] = [condition as string, value === undefined ? null : value];
+  static arrayFilter = (condition: Condition, value?: any): string => {
+    const values: any[] = [condition, value === undefined ? null : value];
     return new Operator("arrayFilter", values).toString();
   };
templates/go/operator.go.twig (1)

88-99: Broaden zero-divisor checks to all numeric kinds.

Current switch only covers int and float64. Calls with int32, int64, uint, float32, etc., can bypass validation.

-func Divide(divisor interface{}, min ...interface{}) string {
-	// Check for zero divisor
-	switch v := divisor.(type) {
-	case int:
-		if v == 0 {
-			panic("divisor cannot be zero")
-		}
-	case float64:
-		if v == 0.0 {
-			panic("divisor cannot be zero")
-		}
-	}
+func Divide(divisor interface{}, min ...interface{}) string {
+	// Check for zero divisor across common numeric kinds
+	switch v := divisor.(type) {
+	case int, int8, int16, int32, int64:
+		if fmt.Sprintf("%d", v) == "0" {
+			panic("divisor cannot be zero")
+		}
+	case uint, uint8, uint16, uint32, uint64, uintptr:
+		// Unsigned zeros are still zero
+		if fmt.Sprintf("%d", v) == "0" {
+			panic("divisor cannot be zero")
+		}
+	case float32:
+		if v == 0 {
+			panic("divisor cannot be zero")
+		}
+	case float64:
+		if v == 0 {
+			panic("divisor cannot be zero")
+		}
+	}
@@
-func Modulo(divisor interface{}) string {
-	switch v := divisor.(type) {
-	case int:
-		if v == 0 {
-			panic("divisor cannot be zero")
-		}
-	case float64:
-		if v == 0.0 {
-			panic("divisor cannot be zero")
-		}
-	}
+func Modulo(divisor interface{}) string {
+	switch v := divisor.(type) {
+	case int, int8, int16, int32, int64:
+		if fmt.Sprintf("%d", v) == "0" {
+			panic("divisor cannot be zero")
+		}
+	case uint, uint8, uint16, uint32, uint64, uintptr:
+		if fmt.Sprintf("%d", v) == "0" {
+			panic("divisor cannot be zero")
+		}
+	case float32:
+		if v == 0 {
+			panic("divisor cannot be zero")
+		}
+	case float64:
+		if v == 0 {
+			panic("divisor cannot be zero")
+		}
+	}

Also applies to: 110-120

templates/web/src/operator.ts.twig (2)

1-3: Simplify list typing.

any[] covers the rest; prefer a single alias (or readonly unknown[]) to reduce surface area.

-type OperatorValuesSingle = string | number | boolean;
-export type OperatorValuesList = string[] | number[] | boolean[] | any[];
-export type OperatorValues = OperatorValuesSingle | OperatorValuesList;
+type OperatorValuesSingle = string | number | boolean;
+export type OperatorValuesList = any[];
+export type OperatorValues = OperatorValuesSingle | OperatorValuesList;

21-43: Make Operator immutable.

Same rationale as Node: prevent post-construction mutations.

 export class Operator {
-  method: string;
-  values: OperatorValuesList | undefined;
+  readonly method: string;
+  readonly values: ReadonlyArray<unknown> | undefined;
@@
-    if (values !== undefined) {
-      if (Array.isArray(values)) {
-        this.values = values;
-      } else {
-        this.values = [values] as OperatorValuesList;
-      }
-    }
+    if (values !== undefined) {
+      const arr = Array.isArray(values) ? values : [values];
+      this.values = Object.freeze([...arr]);
+    }
templates/php/src/Operator.php.twig (2)

1-1: Enable strict types.

Improves type safety across the template outputs.

-<?php
+<?php
+declare(strict_types=1);

34-37: Harden JSON encoding in __toString.

Avoids returning non-string on encoding failure and improves readability; keeps behavior.

-    public function __toString(): string
-    {
-        return json_encode($this);
-    }
+    public function __toString(): string
+    {
+        $json = json_encode($this, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
+        return $json === false ? '' : $json;
+    }
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

44-53: Stronger divisor validation (NaN/Infinity).

Block non-finite divisors to avoid emitting invalid operator payloads.

-        fun divide(divisor: Number, min: Number? = null): String {
-            require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" }
+        fun divide(divisor: Number, min: Number? = null): String {
+            val d = divisor.toDouble()
+            require(d.isFinite() && d != 0.0) { "Divisor must be a finite, non-zero number" }
             val values = mutableListOf<Any?>(divisor)
             min?.let { values.add(it) }
             return Operator("divide", values).toJson()
         }
@@
-        fun modulo(divisor: Number): String {
-            require(divisor.toDouble() != 0.0) { "Divisor cannot be zero" }
+        fun modulo(divisor: Number): String {
+            val d = divisor.toDouble()
+            require(d.isFinite() && d != 0.0) { "Divisor must be a finite, non-zero number" }
             return Operator("modulo", listOf(divisor)).toJson()
         }

Also applies to: 51-54

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c4af38b and fd4027e.

📒 Files selected for processing (17)
  • src/SDK/Language/Apple.php (1 hunks)
  • src/SDK/Language/Web.php (1 hunks)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/index.ts.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
  • tests/languages/web/index.html (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (6)
  • src/SDK/Language/Apple.php
  • templates/python/package/operator.py.twig
  • templates/web/src/index.ts.twig
  • src/SDK/Language/Web.php
  • templates/dotnet/Package/Operator.cs.twig
  • templates/dart/lib/operator.dart.twig
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (17)
  • GitHub Check: build (8.3, Python313)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, PHP83)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, Node16)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, DotNet90)
  • GitHub Check: build (8.3, DartStable)
  • GitHub Check: build (8.3, DartBeta)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: build (8.3, CLINode18)
  • GitHub Check: kotlin (server)
  • GitHub Check: android (client)
  • GitHub Check: swift (server)
  • GitHub Check: apple (client)
  • GitHub Check: flutter (client)
🔇 Additional comments (8)
tests/languages/web/index.html (2)

24-24: Import surface LGTM

Including Operator and Condition in the Appwrite import is correct for the new helpers.


341-341: arrayFilter call matches new API

Using Condition.Equal and passing the value arg keeps cross‑SDK parity with ["equal", "test"].

templates/react-native/src/operator.ts.twig (1)

218-221: arrayFilter parity: good

Emitting ["condition", null] when value is omitted matches other SDKs.

templates/ruby/lib/container/operator.rb.twig (1)

104-107: array_filter null placeholder is correct

Keeping [condition, nil] (→ ["condition", null]) ensures parity with other SDKs.

templates/swift/Sources/Operator.swift.twig (1)

15-22: Null handling implemented correctly

OperatorValue includes .null with proper encode/decode; this preserves ["condition", null] and nested nulls.

Also applies to: 26-61

templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1)

62-90: No issues found—Kotlin tests correctly use array-prefixed function names.

Verification confirms that the Kotlin test file (./tests/languages/kotlin/Tests.kt) consistently calls the prefixed array functions: Operator.arrayAppend(), Operator.arrayPrepend(), Operator.arrayInsert(), Operator.arrayRemove(), Operator.arrayUnique(), Operator.arrayIntersect(), Operator.arrayDiff(), and Operator.arrayFilter(). No unprefixed variants were found. Test parity is maintained.

templates/android/library/src/main/java/io/package/Operator.kt.twig (2)

62-90: No naming parity issues found—review comment is not substantiated.

Android tests (lines 284–291) call the array-prefixed methods (arrayAppend, arrayPrepend, arrayInsert, etc.), which match the method signatures defined in the Kotlin template (lines 62–90). The concern raised in the review comment is not supported by the current codebase.


90-93: Review comment is based on incorrect assumption about Gson default behavior.

The code does not rely on Gson including nulls—it relies on the opposite. By default Gson omits (does not serialize) fields whose value is null. The codebase's GsonBuilder configuration does not call .serializeNulls(), so when arrayFilter passes a null value in the list, it will be excluded from the JSON output, not included. The concern raised in the review is not applicable.

Likely an incorrect or invalid review comment.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

73-99: Method naming may mismatch tests (array vs unprefixed). Please verify*

Past tests referred to append/prepend/insert/remove/unique/intersect/diff/filter without the "array" prefix, which would fail to compile against these APIs. Either add aliases or update tests for consistency.

Run:

#!/bin/bash
# Check Kotlin/Android tests for Operator calls without 'array' prefix
rg -nP 'Operator\.(append|prepend|insert|remove|unique|intersect|diff|filter)\s*\(' tests/ -C2 || true

# Check templates for provided method names
rg -nP 'fun\s+(arrayAppend|arrayPrepend|arrayInsert|arrayRemove|arrayUnique|arrayIntersect|arrayDiff|arrayFilter)\s*\(' templates/android/ templates/kotlin/ -C2
🧹 Nitpick comments (5)
templates/dart/lib/operator.dart.twig (1)

24-36: Narrow values typing and simplify toJson

All call sites pass a List; you can drop the dynamic branch and make serialization clearer.

Apply:

-  final dynamic values;
+  final List<dynamic>? values;
-
-  Operator._(this.method, [this.values = null]);
+  Operator._(this.method, [this.values]);
@@
-  if(values != null) {
-    result['values'] = values is List ? values : [values];
-  }
+  if (values != null) {
+    result['values'] = values;
+  }
templates/python/package/operator.py.twig (1)

25-31: Prefer explicit dict over serializing __dict__

Safer and clearer than relying on default for objects.

Apply:

-    def __str__(self):
-        return json.dumps(
-            self.__dict__,
-            separators=(",", ":"),
-            default=lambda obj: obj.__dict__
-        )
+    def __str__(self):
+        data = {"method": self.method}
+        if hasattr(self, "values"):
+            data["values"] = self.values
+        return json.dumps(data, separators=(",", ":"))
templates/deno/src/operator.ts.twig (1)

251-254: Simplify arrayFilter with nullish coalescing; drop unnecessary cast

Same behavior, less code.

Apply:

-  static arrayFilter = (condition: Condition, value?: any): string => {
-    const values: any[] = [condition as string, value === undefined ? null : value];
-    return new Operator("arrayFilter", values).toString();
-  };
+  static arrayFilter = (condition: Condition, value?: any): string =>
+    new Operator("arrayFilter", [condition, value ?? null]).toString();
templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

81-87: Allow null values for insert/remove to align with List<Any?>

Signatures currently forbid nulls while other APIs accept nullable list elements.

Apply:

-        fun arrayInsert(index: Int, value: Any): String {
+        fun arrayInsert(index: Int, value: Any?): String {
             return Operator("arrayInsert", listOf(index, value)).toJson()
         }
@@
-        fun arrayRemove(value: Any): String {
+        fun arrayRemove(value: Any?): String {
             return Operator("arrayRemove", listOf(value)).toJson()
         }

Also applies to: 85-87

templates/react-native/src/operator.ts.twig (1)

251-254: Tighten arrayFilter implementation

Use nullish coalescing and avoid the cast.

Apply:

-  static arrayFilter = (condition: Condition, value?: any): string => {
-    const values: any[] = [condition as string, value === undefined ? null : value];
-    return new Operator("arrayFilter", values).toString();
-  };
+  static arrayFilter = (condition: Condition, value?: any): string =>
+    new Operator("arrayFilter", [condition, value ?? null]).toString();
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd4027e and 92f13d8.

📒 Files selected for processing (13)
  • templates/android/library/src/main/java/io/package/Operator.kt.twig (1 hunks)
  • templates/dart/lib/operator.dart.twig (1 hunks)
  • templates/deno/src/operator.ts.twig (1 hunks)
  • templates/dotnet/Package/Operator.cs.twig (1 hunks)
  • templates/go/operator.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (1 hunks)
  • templates/node/src/operator.ts.twig (1 hunks)
  • templates/php/src/Operator.php.twig (1 hunks)
  • templates/python/package/operator.py.twig (1 hunks)
  • templates/react-native/src/operator.ts.twig (1 hunks)
  • templates/ruby/lib/container/operator.rb.twig (1 hunks)
  • templates/swift/Sources/Operator.swift.twig (1 hunks)
  • templates/web/src/operator.ts.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • templates/dotnet/Package/Operator.cs.twig
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, WebChromium)
  • GitHub Check: build (8.3, Python313)
  • GitHub Check: build (8.3, Node20)
  • GitHub Check: build (8.3, Node16)
  • GitHub Check: build (8.3, PHP83)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: build (8.3, Go112)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, DotNet60)
  • GitHub Check: build (8.3, DartStable)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: kotlin (server)
  • GitHub Check: swift (server)
  • GitHub Check: android (client)
  • GitHub Check: apple (client)
🔇 Additional comments (12)
templates/kotlin/src/main/kotlin/io/appwrite/Operator.kt.twig (3)

26-71: Excellent validation for arithmetic operations.

The comprehensive NaN, Infinity, and zero-division checks across all numeric operations demonstrate good defensive programming. The consistent validation pattern and use of Kotlin's require() make the code robust and idiomatic.


73-104: Verify nullable type consistency in array operations.

There's an inconsistency in how nullable values are handled:

  • arrayAppend, arrayPrepend, arrayIntersect, arrayDiff accept List<Any?> (nullable elements allowed)
  • arrayInsert and arrayRemove require non-null Any
  • arrayFilter accepts nullable Any?

Is there a reason why you can append/prepend null values but cannot insert or remove them? This might confuse users if the restriction is unintentional.

Consider standardizing to either allow or disallow null values consistently across all single-element array operations:

// Option 1: Allow nulls everywhere
fun arrayInsert(index: Int, value: Any?): String {
    return Operator("arrayInsert", listOf(index, value)).toJson()
}

fun arrayRemove(value: Any?): String {
    return Operator("arrayRemove", listOf(value)).toJson()
}

// Option 2: Explicitly document the restriction if intentional

50-57: Past review concern already addressed.

Regarding the previous comment asking about NaN/Infinity validation on line 53: the validation is already present on lines 51-52, which check both the divisor and optional min parameter before the zero-division check on line 53. The implementation correctly validates all edge cases.

templates/dart/lib/operator.dart.twig (1)

161-165: arrayFilter parity looks correct

Emits the two-slot array with a null placeholder when value is omitted. Matches cross-SDK behavior.

templates/python/package/operator.py.twig (1)

125-129: array_filter parity confirmed

Always emits [condition, value] with None serialized as null when omitted.

templates/android/library/src/main/java/io/package/Operator.kt.twig (1)

101-104: arrayFilter parity looks good

Emits [condition, value] with null preserved when value omitted.

templates/swift/Sources/Operator.swift.twig (1)

1-305: LGTM! Well-structured Swift Operator implementation.

The implementation correctly addresses all previously flagged issues:

  • Null handling with explicit .null case (line 21) and proper encoding/decoding (lines 26-27, 59-60)
  • Empty array preservation and unknown-to-null mapping in convertToOperatorValueArray (lines 113-115, 132-135)
  • Explicit null placeholder in arrayFilter (line 278)
  • Comprehensive validation for arithmetic operations (NaN/Infinity checks, zero-divisor guards)

The API surface is consistent with other language implementations in this PR and provides robust type safety through the OperatorValue enum.

templates/node/src/operator.ts.twig (1)

1-308: LGTM! Clean TypeScript implementation with proper validation.

The Node operator template is well-implemented with:

  • Clear type definitions for operator values (lines 1-3)
  • Comprehensive Condition enum including null checks (lines 5-15)
  • Consistent constructor normalization (lines 36-42)
  • Proper validation for all arithmetic operations (NaN, Infinity, zero-divisor checks)
  • Correct null placeholder handling in arrayFilter (line 252)

The implementation aligns well with the other language templates in this PR and provides a clean, type-safe API for operator construction.

templates/ruby/lib/container/operator.rb.twig (1)

1-145: LGTM! Solid Ruby implementation with comprehensive validation.

The Ruby operator template provides:

  • Clean module structure with Condition constants (lines 3-14)
  • Proper value normalization in the constructor (lines 20-26)
  • JSON serialization with conditional value inclusion (lines 29-33)
  • Thorough validation for arithmetic operations using nan? and infinite? checks
  • Zero-divisor guards for divide and modulo (lines 67, 75)
  • Consistent array_filter behavior that always includes the value parameter (line 116), matching other SDK implementations

The implementation follows Ruby idioms and maintains parity with the other language templates.

templates/go/operator.go.twig (1)

1-277: LGTM! Clean Go implementation with proper error handling.

The Go operator template successfully addresses all previously flagged issues:

  • Removed unused helper functions (no toArray present)
  • Marshal errors properly handled with panic (lines 53-56)
  • Removed omitempty from values field to ensure empty arrays serialize (line 44)
  • ArrayFilter always emits two-element array with explicit nil placeholder (line 221)

Additional strengths:

  • Idiomatic Go patterns with exported/unexported naming conventions
  • Centralized numeric validation helper (lines 28-39)
  • Comprehensive zero-divisor checks in Divide and Modulo (lines 115-125, 138-146)
  • Clean separation between public API (exported functions) and internal serialization logic
templates/php/src/Operator.php.twig (1)

1-331: LGTM! Comprehensive PHP implementation with proper type safety.

The PHP operator template successfully resolves all previously identified issues:

  • Zero-divisor validation in both divide (lines 128-130) and modulo (lines 149-151)
  • Consistent NaN/Infinity checks across all arithmetic operations
  • Proper null handling in arrayFilter (line 263)

Additional strengths:

  • Modern PHP type hints (int|float, mixed) for better IDE support and runtime safety
  • JsonSerializable implementation for clean serialization (lines 39-45)
  • Comprehensive PHPDoc comments for all public methods
  • Value normalization in constructor (lines 27-31) handles both arrays and scalar values
  • Consistent factory method pattern returning serialized strings

The implementation provides a clean, type-safe API that aligns well with PHP best practices and the other language templates in this PR.

templates/web/src/operator.ts.twig (1)

1-308: LGTM! Solid Web TypeScript implementation.

The Web operator template successfully addresses all previously flagged issues:

  • Division by zero validation in divide (lines 134-136)
  • Zero-divisor check in modulo (lines 154-156)
  • Correct null placeholder handling in arrayFilter (line 252)

The implementation mirrors the Node template structure, which is appropriate for maintaining consistency across JavaScript/TypeScript environments. All arithmetic operations include comprehensive validation (NaN, Infinity, zero-divisor checks), and the type definitions provide good developer experience with IntelliSense support.

The factory method pattern returning JSON strings is clean and consistent with the broader PR's cross-language operator API design.

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.

2 participants