Skip to content

Conversation

@abnegate
Copy link
Member

@abnegate abnegate commented Dec 11, 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

Release Notes

  • New Features

    • Added support for request models across all SDKs, enabling typed input models for API requests.
    • Added new mock API endpoints for testing player creation (single and batch operations).
  • Chores

    • Updated PHP minimum version requirements (8.2 → 8.3/8.4).
    • Enhanced type safety with strict return types across codebase.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 11, 2025

Walkthrough

This pull request introduces comprehensive support for request models across the SDK generator platform. Changes include: (1) PHP version updates in composer.json files (8.2→8.3, 8.2→8.4); (2) addition of Player model and validator classes in the mock server with new API endpoints for model testing; (3) type safety enhancements across core Spec classes with new abstract method return types and a new getRequestModels() method; (4) parallel updates to all language generators (Android, Apple, Dart, DotNet, Go, JS, Kotlin, Node, PHP, Python, Ruby, Swift, Web, etc.) to generate request model files and resolve request model types; (5) new Twig templates for generating language-specific request model classes; (6) test infrastructure expansion with Base constants for model responses and updates to all test suites; (7) specification updates adding player definition and new mock endpoints.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Type annotation scope: Multiple core files (Spec.php, Swagger2.php, Response.php) introduce numerous return type declarations on abstract methods and signature updates—requires careful verification of consistency with implementations across all language subclasses.
  • Language generator parallelism: 15+ language generators (Android, Apple, Dart, DotNet, Go, Kotlin, Node, PHP, Python, Ruby, Swift, Web, etc.) all receive similar but language-specific modifications to getTypeName and getFiles methods. Each requires individual validation that type mapping logic is correct and consistent with language semantics.
  • Template correctness: New Twig templates for each language handle property serialization, enum conversion, and nested structures (sub_schema, arrays). Variations in syntax and semantics per language demand language-specific expertise.
  • Test data consistency: All test files receive MODEL_RESPONSES additions; verify that the mock-server endpoints and response payloads align with test expectations across all languages.
  • Heterogeneous changes: While the addition follows a consistent pattern (request model support), the implementation spans core logic, multiple generators, multiple templates, and test suites. Each domain requires separate reasoning.

Areas requiring extra attention

  • Spec.php and Swagger2.php: Verify that all new return type annotations align with subclass implementations in derived Spec classes (e.g., OpenAPI3.php if present); check getRequestModels() implementation consistency.
  • Language generators' getTypeName logic: Cross-reference the handling of parameter['array']['model'] and parameter['model'] against language-specific type syntax (e.g., List<> in Java/Kotlin vs. array in PHP); verify no regressions in existing enum/items handling.
  • Template serialization logic: In particular, Dart, DotNet, Go, Kotlin, PHP, Python, Ruby, Swift templates—verify toMap()/toJson() implementations correctly handle sub_schema recursion, enum value extraction, and nullable properties.
  • Mock server endpoints: Validate that POST /v1/mock/tests/general/models and /models/array correctly use PlayerValidator and Player model; ensure PlayerValidator.isValid() properly guards request data.
  • Test expectations: Confirm that Base::MODEL_RESPONSES entries (POST:/v1/mock/tests/general/models:passed, POST:/v1/mock/tests/general/models/array:passed) match actual mock-server response status codes and that language test files construct Player objects with consistent field values.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Request model support' directly and clearly summarizes the main objective of the PR, which adds comprehensive request model generation support across multiple SDK languages and infrastructure.
Docstring Coverage ✅ Passed Docstring coverage is 84.15% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat-request-model

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f9e6884 and 9dfa14d.

📒 Files selected for processing (3)
  • src/SDK/Language/Node.php (2 hunks)
  • templates/node/src/models/requestModel.ts.twig (1 hunks)
  • templates/ruby/lib/container/models/request_model.rb.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/SDK/Language/Node.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). (20)
  • GitHub Check: build (8.3, Ruby27)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, WebNode)
  • GitHub Check: build (8.3, Python312)
  • GitHub Check: build (8.3, Node16)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, Node18)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, DotNet90)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, DotNet60)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, CLINode16)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: kotlin (server)
  • GitHub Check: swift (server)
  • GitHub Check: android (client)
  • GitHub Check: apple (client)
  • GitHub Check: flutter (client)
🔇 Additional comments (7)
templates/node/src/models/requestModel.ts.twig (3)

1-12: LGTM: Import deduplication implemented correctly.

The import deduplication logic properly prevents duplicate imports by tracking imported enums and schemas in arrays and checking membership before generating import statements.


14-24: LGTM: Interface definition is well-structured.

The interface properly declares all properties with appropriate optional markers and includes JSDoc documentation for both the interface and individual properties.


26-35: LGTM: ToMap function handles all property types correctly.

The function properly handles the conversion of request models to plain objects with appropriate handling for:

  • Sub-schema properties (both single and array)
  • Optional chaining for optional array properties
  • Enum properties
  • Simple properties

The truthy check for non-array sub_schemas is safe since objects are only falsy when null or undefined.

templates/ruby/lib/container/models/request_model.rb.twig (4)

1-8: LGTM: Module structure and attr_readers properly defined.

The frozen_string_literal magic comment is correctly formatted, and the module/class structure with attr_readers follows Ruby conventions.


10-27: LGTM: Initialize method correctly handles required and optional properties.

The initialization logic properly validates enum properties while allowing optional properties to remain nil without validation. The ternary logic on Line 21 correctly skips validation when an optional enum property is nil.


29-36: LGTM: to_map method includes proper nil safety.

The safe navigation operator &. is correctly used for sub_schema properties (Line 32), preventing NoMethodError when optional properties are nil. Both array and single object sub_schemas are handled safely.


38-40: LGTM: to_json delegation is correct.

The method properly delegates to to_map.to_json(*args), passing through any arguments as expected.


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: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/SDK/Language/Ruby.php (1)

269-269: Pre-existing typo: 'nill' should be 'nil'.

This is a pre-existing issue not introduced by this PR, but worth noting: Ruby's null value is nil, not nill.

-                    $output .= 'nill';
+                    $output .= 'nil';
src/Spec/Spec.php (1)

166-188: Stale docblock parameter.

Line 168 references @param array $parameter but the method signature has $type as the third parameter, not $parameter.

     /**
      * Set Attribute
      *
      * Method for setting a specific field attribute
      *
      * @param string $key
      * @param mixed $value
-     * @param array $parameter
+     * @param string $type
      * @return mixed
      */
     public function setAttribute(string $key, mixed $value, $type = self::SET_TYPE_ASSIGN): mixed
🧹 Nitpick comments (17)
templates/php/src/Services/Service.php.twig (1)

9-23: Model imports for service methods look good; consider separating enum/model dedupe

The new parameter.model handling correctly adds Models\... imports only once per model and mirrors the existing enum pattern, so generated services will have the right model classes in scope.

Since added is shared between enums and models, if you ever have an enum and a model with the same base name, one of the use statements could be skipped. If that’s a realistic case, consider tracking them separately (e.g., addedEnums vs addedModels) to avoid accidental collisions.

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

347-366: Improved CLI type resolution for model-backed params

The new branches in getTypeName() for array.model and model nicely ensure model-backed parameters resolve to a concrete PascalCase type (with [] for arrays) instead of falling through to generic mappings—this should make generated CLI types much more accurate.

Minor nit: the docblock still refers to the second parameter as $nestedTypes, but the signature uses $spec. If you touch this again, aligning those names would avoid confusion for readers and tooling.

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

131-150: React Native model types now resolved explicitly

The added checks for array.model and model in getTypeName() correctly map model-backed parameters to Models.<PascalCase> (and [] for arrays), which should give much stronger typings for request models and other modeled inputs without disturbing the existing responseModel-based object handling.

Similar to CLI, the docblock still names the second argument $nestedTypes while the method uses $method; if you revisit this, updating the annotation would keep docs and implementation in sync.

templates/php/src/Models/RequestModel.php.twig (2)

74-74: Simplify the complex ternary logic for better readability.

Line 74 contains deeply nested ternary operators handling sub_schema, arrays, and enums in a single expression. This makes the template difficult to read and maintain.

Consider breaking this into a Twig macro or helper function that handles the conversion logic more explicitly:

'{{ property.name }}' => {{ property | convertToArrayValue }},

Or split the logic across multiple lines using Twig's set/if blocks before the array definition.


84-86: Add error handling for JSON encoding.

The json_encode() call can return false on failure (e.g., for non-UTF-8 strings or circular references), but the method signature promises a string return type.

Consider adding error handling:

 public function toJson(): string
 {
-    return json_encode($this->toArray());
+    $json = json_encode($this->toArray());
+    if ($json === false) {
+        throw new \RuntimeException('Failed to encode model to JSON: ' . json_last_error_msg());
+    }
+    return $json;
 }
tests/languages/ruby/tests.rb (1)

93-96: Optional: Add trailing comma for consistency.

RuboCop suggests adding a trailing comma after the last array item for consistency with Ruby style conventions.

Apply this diff:

 response = general.create_players(players: [
     {id: 'player1', name: 'John Doe', score: 100},
-    {id: 'player2', name: 'Jane Doe', score: 200}
+    {id: 'player2', name: 'Jane Doe', score: 200},
 ])
src/SDK/Language/Swift.php (2)

310-314: Request-model file mapping for Swift looks consistent; double-check path convention

The new requestModel scope entry mirrors the existing definition scope (same ...{{ spec.title | caseUcfirst}}Models/... and swift/Sources/Models/*.twig usage), so it should integrate cleanly into generation.

One thing to verify: other Swift files (e.g., Error.swift, UploadProgress.swift) use /Sources/{{ spec.title | caseUcfirst}}/Models/... with a slash before Models, while both the definition and new requestModel entries use {{ spec.title | caseUcfirst}}Models without the slash. If the intention is Sources/AppwriteModels/..., this is fine; if the desired layout is Sources/Appwrite/Models/..., you may want to adjust both entries together for consistency.


335-341: Model and array-of-model type resolution in getTypeName looks correct; consider minor robustness tweak

The new branches correctly map:

  • array.model[<SpecTitle>Models.<ModelName>]
  • model<SpecTitle>Models.<ModelName> or [<SpecTitle>Models.<ModelName>] when type === TYPE_ARRAY.

To make this a bit more defensive in case $parameter['array'] or $parameter['type'] is missing for some inputs, you could mirror the later TYPE_ARRAY branch and use null-coalescing/local temporaries, e.g.:

$array = $parameter['array'] ?? null;
if (!empty($array['model'])) {
    return '[' . ($spec['title'] ?? '') . 'Models.' . $this->toPascalCase($array['model']) . ']';
}
$model = $parameter['model'] ?? null;
if (!empty($model)) {
    $modelType = ($spec['title'] ?? '') . 'Models.' . $this->toPascalCase($model);
    return (($parameter['type'] ?? null) === self::TYPE_ARRAY) ? '[' . $modelType . ']' : $modelType;
}

This keeps behavior the same for well-formed parameters while reducing the chance of notices if a caller passes an unexpected shape.

src/SDK/SDK.php (1)

707-717: LGTM! Request model generation implemented correctly.

The new requestModel case follows the established pattern used for definition generation. The implementation properly iterates through request models, respects exclusion rules, and renders templates.

Consider whether the setExclude() method (line 765) and exclude() method (line 788) should be extended to support request model exclusions in the future. The current implementation only handles services, methods, and definitions, which may be sufficient for now but could be expanded if selective request model exclusion becomes necessary.

mock-server/src/Utopia/Model/Player.php (1)

16-23: Consider defensive handling for missing array keys.

The fromArray method directly accesses array keys without checking for their existence. If a malformed payload is passed, this will throw an Undefined array key error rather than a more descriptive exception.

 public static function fromArray(array $value): static
 {
+    if (!isset($value['id'], $value['name'], $value['score'])) {
+        throw new \InvalidArgumentException('Missing required keys: id, name, score');
+    }
     return new static(
         id: $value['id'],
         name: $value['name'],
         score: $value['score'],
     );
 }
templates/swift/Sources/Models/RequestModel.swift.twig (1)

36-43: Consider extracting complex mapping logic for readability.

The inline logic on line 39 handles multiple cases (sub_schema arrays, sub_schema objects, enums, plain values) in a single dense line. While functional, this could be challenging to maintain.

Consider breaking out the value mapping into a Twig macro or splitting across multiple lines for clarity:

{%~ for property in requestModel.properties %}
{% set propName = property.name | escapeSwiftKeyword | removeDollarSign %}
{% set optionalChain = property.required ? '' : '?' %}
{% if property.sub_schema %}
{% if property.type == 'array' %}
            "{{ property.name }}": {{ propName }}{{ optionalChain }}.map { $0.toMap() },
{% else %}
            "{{ property.name }}": {{ propName }}{{ optionalChain }}.toMap(),
{% endif %}
{% elseif property.enum %}
            "{{ property.name }}": {{ propName }}{{ optionalChain }}.rawValue,
{% else %}
            "{{ property.name }}": {{ propName }},
{% endif %}
{%~ endfor %}
templates/android/library/src/main/java/io/package/models/RequestModel.kt.twig (1)

1-30: Template duplication with templates/kotlin/.../RequestModel.kt.twig.

This template is identical to templates/kotlin/src/main/kotlin/io/appwrite/models/RequestModel.kt.twig. While this may be intentional to maintain separate Android and Kotlin SDK templates, consider whether a shared template could reduce maintenance burden if the logic remains identical.

The template itself is correctly structured for generating Kotlin request model classes.

templates/python/package/models/request_model.py.twig (1)

33-36: Consider moving json import to file level.

The json module import inside to_json() works but is unconventional. Moving it to the file-level imports would be more Pythonic and avoid repeated import overhead if called multiple times.

-from typing import Optional, List, Dict, Any
+from typing import Optional, List, Dict, Any
+import json
 ...
     def to_json(self) -> str:
         """Convert the model to a JSON string."""
-        import json
         return json.dumps(self.to_map())
templates/ruby/lib/container/models/request_model.rb.twig (1)

29-40: Inconsistent use of removeDollarSign filter.

On line 32, removeDollarSign is applied to properties with sub_schema but not to regular properties in the else branch. If the property name can contain a $ character, this inconsistency could cause issues.

Consider applying the filter consistently:

-                    "{{ property.name }}": {% if property.sub_schema %}{% if property.type == 'array' %}@{{ property.name | caseSnake | escapeKeyword | removeDollarSign }}.map { |it| it.to_map }{% else %}@{{property.name | caseSnake | escapeKeyword | removeDollarSign }}.to_map{% endif %}{% else %}@{{property.name | caseSnake | escapeKeyword }}{% endif %}{% if not loop.last %},{% endif %}
+                    "{{ property.name }}": {% if property.sub_schema %}{% if property.type == 'array' %}@{{ property.name | caseSnake | escapeKeyword | removeDollarSign }}.map { |it| it.to_map }{% else %}@{{property.name | caseSnake | escapeKeyword | removeDollarSign }}.to_map{% endif %}{% else %}@{{property.name | caseSnake | escapeKeyword | removeDollarSign }}{% endif %}{% if not loop.last %},{% endif %}
mock-server/src/Utopia/Response.php (2)

32-36: Unused constructor parameter.

The $response parameter is declared but never used in the constructor body. If this is intentional (to satisfy the parent signature without using it), consider adding a comment or suppression annotation to clarify intent.

     public function __construct(SwooleResponse $response)
     {
+        // Intentionally not calling parent constructor or using $response
     }

257-260: Consider using strict null comparison.

Using != for null comparison works but !== is preferred for clarity and to avoid potential type coercion issues.

     public static function hasFilter(): bool
     {
-        return self::$filter != null;
+        return self::$filter !== null;
     }
src/Spec/Swagger2.php (1)

516-559: Significant code duplication with getDefinitions().

getRequestModels() shares ~90% of its logic with getDefinitions(). Consider extracting the common property enrichment logic into a private helper method to reduce duplication and ensure consistent behavior.

Also, the same description type issue exists on line 527:

             $model = [
                 'name' => $key,
                 'properties' => $schema['properties'] ?? [],
-                'description' => $schema['description'] ?? [],
+                'description' => $schema['description'] ?? '',
                 'required' => $schema['required'] ?? [],
                 'additionalProperties' => $schema['additionalProperties'] ?? []
             ];
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ac31311 and 55106f4.

⛔ Files ignored due to path filters (1)
  • mock-server/composer.lock is excluded by !**/*.lock
📒 Files selected for processing (89)
  • composer.json (1 hunks)
  • example.php (1 hunks)
  • mock-server/app/http.php (3 hunks)
  • mock-server/composer.json (1 hunks)
  • mock-server/src/Utopia/Model.php (2 hunks)
  • mock-server/src/Utopia/Model/Player.php (1 hunks)
  • mock-server/src/Utopia/Response.php (6 hunks)
  • mock-server/src/Utopia/Validator/Player.php (1 hunks)
  • src/SDK/Language/Android.php (1 hunks)
  • src/SDK/Language/Apple.php (1 hunks)
  • src/SDK/Language/CLI.php (1 hunks)
  • src/SDK/Language/Dart.php (2 hunks)
  • src/SDK/Language/Deno.php (1 hunks)
  • src/SDK/Language/DotNet.php (2 hunks)
  • src/SDK/Language/Flutter.php (1 hunks)
  • src/SDK/Language/Go.php (2 hunks)
  • src/SDK/Language/JS.php (1 hunks)
  • src/SDK/Language/Kotlin.php (2 hunks)
  • src/SDK/Language/Node.php (2 hunks)
  • src/SDK/Language/PHP.php (2 hunks)
  • src/SDK/Language/Python.php (2 hunks)
  • src/SDK/Language/ReactNative.php (1 hunks)
  • src/SDK/Language/Ruby.php (2 hunks)
  • src/SDK/Language/Swift.php (2 hunks)
  • src/SDK/Language/Web.php (1 hunks)
  • src/SDK/SDK.php (2 hunks)
  • src/Spec/Spec.php (5 hunks)
  • src/Spec/Swagger2.php (8 hunks)
  • templates/android/library/src/main/java/io/package/models/RequestModel.kt.twig (1 hunks)
  • templates/dart/lib/models.dart.twig (1 hunks)
  • templates/dart/lib/src/models/request_model.dart.twig (1 hunks)
  • templates/dotnet/Package/Models/RequestModel.cs.twig (1 hunks)
  • templates/go/models/request_model.go.twig (1 hunks)
  • templates/kotlin/src/main/kotlin/io/appwrite/models/RequestModel.kt.twig (1 hunks)
  • templates/node/src/models/request_model.ts.twig (1 hunks)
  • templates/php/src/Models/RequestModel.php.twig (1 hunks)
  • templates/php/src/Services/Service.php.twig (1 hunks)
  • templates/python/package/models/request_model.py.twig (1 hunks)
  • templates/ruby/lib/container/models/request_model.rb.twig (1 hunks)
  • templates/swift/Sources/Models/RequestModel.swift.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 (2 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/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 (1 hunks)
  • tests/languages/dotnet/Tests.cs (1 hunks)
  • tests/languages/flutter/tests.dart (1 hunks)
  • tests/languages/kotlin/Tests.kt (2 hunks)
  • tests/languages/node/test.js (1 hunks)
  • tests/languages/php/test.php (2 hunks)
  • tests/languages/python/tests.py (1 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 (1 hunks)
  • tests/resources/spec.json (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (56)
tests/languages/web/node.js (1)
tests/languages/node/test.js (1)
  • general (28-28)
src/SDK/Language/Dart.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/Android5Java17Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/FlutterStableTest.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Python311Test.php (1)
tests/Base.php (1)
  • Base (17-335)
mock-server/app/http.php (2)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
tests/Deno1303Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/languages/swift/Tests.swift (4)
tests/languages/node/test.js (1)
  • general (28-28)
tests/languages/web/node.js (1)
  • general (11-11)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
tests/DartBetaTest.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/KotlinJava11Test.php (1)
tests/Base.php (1)
  • Base (17-335)
mock-server/src/Utopia/Validator/Player.php (4)
mock-server/src/Utopia/Model.php (2)
  • Model (7-166)
  • getType (67-67)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
src/Spec/Spec.php (1)
  • getDescription (53-53)
src/Spec/Swagger2.php (1)
  • getDescription (20-23)
tests/WebChromiumTest.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Ruby27Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Python313Test.php (1)
tests/Base.php (1)
  • Base (17-335)
mock-server/src/Utopia/Model/Player.php (2)
mock-server/src/Utopia/Model.php (1)
  • Model (7-166)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
tests/Node16Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/languages/apple/Tests.swift (4)
tests/languages/node/test.js (1)
  • general (28-28)
tests/languages/web/node.js (1)
  • general (11-11)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
src/SDK/Language/Web.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/KotlinJava8Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/languages/node/test.js (1)
tests/languages/web/node.js (2)
  • response (4-4)
  • general (11-11)
src/SDK/Language/DotNet.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/PHP80Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/ReactNative.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/languages/deno/tests.ts (2)
tests/languages/node/test.js (2)
  • response (18-18)
  • general (28-28)
tests/languages/web/node.js (2)
  • response (4-4)
  • general (11-11)
tests/Python310Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Android14Java11Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Python312Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/Python.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/WebNodeTest.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Swift56Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Android14Java8Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/CLI.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/Android14Java17Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/Ruby30Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/PHP83Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/Deno.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/AppleSwift56Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/DotNet60Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/Kotlin.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/DartStableTest.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/Node.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
src/SDK/Language/JS.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/languages/dotnet/Tests.cs (4)
tests/languages/node/test.js (1)
  • general (28-28)
tests/languages/web/node.js (1)
  • general (11-11)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
src/SDK/Language/PHP.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
src/SDK/Language/Go.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/languages/kotlin/Tests.kt (3)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
tests/languages/android/Tests.kt (1)
  • writeToFile (315-318)
src/SDK/SDK.php (2)
src/Spec/Spec.php (1)
  • getRequestModels (133-133)
src/Spec/Swagger2.php (1)
  • getRequestModels (516-559)
tests/Ruby31Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/FlutterBetaTest.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/languages/php/test.php (2)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
tests/DotNet80Test.php (1)
tests/Base.php (1)
  • Base (17-335)
tests/KotlinJava17Test.php (1)
tests/Base.php (1)
  • Base (17-335)
src/SDK/Language/Swift.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
tests/DotNet90Test.php (1)
tests/Base.php (1)
  • Base (17-335)
mock-server/src/Utopia/Response.php (1)
mock-server/src/Utopia/Model.php (2)
  • filter (50-53)
  • Model (7-166)
src/Spec/Spec.php (1)
src/Spec/Swagger2.php (19)
  • getTitle (12-15)
  • getDescription (20-23)
  • getNamespace (28-31)
  • getVersion (36-39)
  • getEndpoint (44-49)
  • getEndpointDocs (54-59)
  • getLicenseName (64-67)
  • getLicenseURL (72-75)
  • getContactName (80-83)
  • getContactURL (88-91)
  • getContactEmail (96-99)
  • getServices (104-136)
  • getMethods (300-339)
  • getTargetNamespace (432-435)
  • getGlobalHeaders (440-457)
  • getDefinitions (459-509)
  • getRequestModels (516-559)
  • getRequestEnums (564-587)
  • getResponseEnums (592-629)
🪛 GitHub Actions: Twig Linting
templates/python/package/models/request_model.py.twig

[error] 6-6: H014 6:3 Found extra blank lines. endfor %}. djlint lint reported a formatting issue.

🪛 RuboCop (1.81.7)
tests/languages/ruby/tests.rb

[convention] 95-95: Put a comma after the last item of a multiline array.

(Style/TrailingCommaInArrayLiteral)

⏰ 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: build (8.3, Python313)
  • GitHub Check: build (8.3, Swift56)
  • GitHub Check: build (8.3, Python39)
  • GitHub Check: build (8.3, Ruby30)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, WebNode)
  • GitHub Check: build (8.3, PHP83)
  • GitHub Check: build (8.3, DartBeta)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: dotnet (server)
  • GitHub Check: kotlin (server)
  • GitHub Check: swift (server)
  • GitHub Check: flutter (client)
  • GitHub Check: android (client)
  • GitHub Check: apple (client)

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 (3)
templates/node/src/models/request_model.ts.twig (1)

28-28: Consider refactoring for readability.

Line 28 contains nested conditionals spanning ~400 characters, making it difficult to parse and maintain. While the logic is correct, splitting the conditions or using intermediate variables would improve clarity.

Example refactoring with intermediate template variables:

        {%~ for property in requestModel.properties %}
        {%~ set propName = property.name %}
        {%~ set propKey = property.name | escapeKeyword %}
        {%~ if property.sub_schema %}
        {%~ if property.type == 'array' %}
        '{{ propName }}': model.{{ propKey }}{% if not property.required %}?{% endif %}.map(item => {{ property.sub_schema | caseCamel }}ToMap(item)),
        {%~ else %}
        '{{ propName }}': model.{{ propKey }} ? {{ property.sub_schema | caseCamel }}ToMap(model.{{ propKey }}) : undefined,
        {%~ endif %}
        {%~ elseif property.enum %}
        '{{ propName }}': model.{{ propKey }},
        {%~ else %}
        '{{ propName }}': model.{{ propKey }},
        {%~ endif %}
        {%~ endfor %}
src/SDK/Language/DotNet.php (1)

524-541: Consider consolidating with the existing sub_schema function.

The getPropertyType method largely duplicates the logic in the existing sub_schema TwigFunction (lines 550-571). Both handle sub_schema resolution, enum conversion, and fallback to getTypeName. The main difference is that sub_schema adds nullability markers (?) for non-required properties.

Consider extracting the shared type-resolution logic into a common helper method that both can call, then handle nullability as a separate concern:

+    protected function resolvePropertyTypeName(array $property, array $spec = []): string
+    {
+        if (isset($property['sub_schema']) && !empty($property['sub_schema'])) {
+            $type = $this->toPascalCase($property['sub_schema']);
+            if ($property['type'] === 'array') {
+                return 'List<' . $type . '>';
+            }
+            return $type;
+        }
+
+        if (isset($property['enum']) && !empty($property['enum'])) {
+            $enumName = $property['enumName'] ?? $property['name'];
+            return 'Appwrite.Enums.' . $this->toPascalCase($enumName);
+        }
+
+        return $this->getTypeName($property, $spec);
+    }
+
     protected function getPropertyType(array $property, array $spec = []): string
     {
-        if (isset($property['sub_schema']) && !empty($property['sub_schema'])) {
-            $type = $this->toPascalCase($property['sub_schema']);
-
-            if ($property['type'] === 'array') {
-                return 'List<' . $type . '>';
-            }
-            return $type;
-        }
-
-        if (isset($property['enum']) && !empty($property['enum'])) {
-            $enumName = $property['enumName'] ?? $property['name'];
-            return 'Appwrite.Enums.' . $this->toPascalCase($enumName);
-        }
-
-        return $this->getTypeName($property, $spec);
+        return $this->resolvePropertyTypeName($property, $spec);
     }

Then update the sub_schema function similarly and add nullability there.

src/Spec/Swagger2.php (1)

511-559: Consider extracting shared property enrichment logic.

The new getRequestModels() method correctly implements request model extraction, but the property enrichment loop (lines 532-554) duplicates the logic from getDefinitions() (lines 478-504).

Consider extracting the shared property processing into a private helper method:

private function enrichModelProperties(array &$model): void
{
    if (!isset($model['properties'])) {
        return;
    }
    
    foreach ($model['properties'] as $name => $def) {
        $model['properties'][$name]['name'] = $name;
        $model['properties'][$name]['description'] = $def['description'] ?? '';
        $model['properties'][$name]['example'] = $def['x-example'] ?? null;
        $model['properties'][$name]['required'] = in_array($name, $model['required']);
        
        if (isset($def['items']['$ref'])) {
            $model['properties'][$name]['sub_schema'] = str_replace('#/definitions/', '', $def['items']['$ref']);
        }
        
        if (isset($def['items']['x-anyOf'])) {
            $model['properties'][$name]['sub_schemas'] = \array_map(
                fn($schema) => str_replace('#/definitions/', '', $schema['$ref']), 
                $def['items']['x-anyOf']
            );
        }
        
        if (isset($def['items']['x-oneOf'])) {
            $model['properties'][$name]['sub_schemas'] = \array_map(
                fn($schema) => str_replace('#/definitions/', '', $schema['$ref']), 
                $def['items']['x-oneOf']
            );
        }
        
        if (isset($def['enum'])) {
            $model['properties'][$name]['enum'] = $def['enum'];
            $model['properties'][$name]['enumName'] = $def['x-enum-name'] ?? ucfirst($model['name']) . ucfirst($name);
            $model['properties'][$name]['enumKeys'] = $def['x-enum-keys'] ?? [];
        }
    }
}

Then both methods could call $this->enrichModelProperties($model); instead of duplicating the loop.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 55106f4 and 9857b94.

📒 Files selected for processing (6)
  • mock-server/app/http.php (2 hunks)
  • src/SDK/Language/DotNet.php (3 hunks)
  • src/Spec/Spec.php (5 hunks)
  • src/Spec/Swagger2.php (8 hunks)
  • templates/node/src/models/request_model.ts.twig (1 hunks)
  • templates/php/src/Client.php.twig (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/Spec/Spec.php (1)
src/Spec/Swagger2.php (19)
  • getTitle (12-15)
  • getDescription (20-23)
  • getNamespace (28-31)
  • getVersion (36-39)
  • getEndpoint (44-49)
  • getEndpointDocs (54-59)
  • getLicenseName (64-67)
  • getLicenseURL (72-75)
  • getContactName (80-83)
  • getContactURL (88-91)
  • getContactEmail (96-99)
  • getServices (104-136)
  • getMethods (300-339)
  • getTargetNamespace (432-435)
  • getGlobalHeaders (440-457)
  • getDefinitions (459-509)
  • getRequestModels (516-559)
  • getRequestEnums (564-587)
  • getResponseEnums (592-629)
src/Spec/Swagger2.php (1)
src/Spec/Spec.php (17)
  • getTitle (48-48)
  • getAttribute (144-159)
  • getDescription (53-53)
  • getNamespace (58-58)
  • getVersion (63-63)
  • getEndpoint (68-68)
  • getEndpointDocs (73-73)
  • getLicenseName (78-78)
  • getLicenseURL (83-83)
  • getContactName (88-88)
  • getContactURL (93-93)
  • getContactEmail (98-98)
  • getServices (103-103)
  • getMethods (109-109)
  • getGlobalHeaders (121-121)
  • getDefinitions (126-126)
  • getRequestModels (133-133)
mock-server/app/http.php (4)
mock-server/src/Utopia/Model.php (1)
  • Model (7-166)
mock-server/src/Utopia/Model/Player.php (1)
  • Player (7-24)
mock-server/src/Utopia/Validator/Player.php (1)
  • Player (8-29)
mock-server/src/Utopia/Response.php (1)
  • Response (12-273)
⏰ 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). (2)
  • GitHub Check: swift (server)
  • GitHub Check: flutter (client)
🔇 Additional comments (15)
mock-server/app/http.php (3)

29-30: LGTM! Clean import structure.

The imports are properly organized with appropriate aliasing to prevent naming conflicts between the Player model and Player validator.


525-539: LGTM! Well-structured request model endpoint.

The endpoint follows the established mock endpoint pattern and correctly integrates the new request model functionality with proper validation and typing.


541-556: LGTM! Nice use of type documentation.

The endpoint correctly handles array request models with proper validation. The PHP docblock on line 555 providing Player[] type information is a good practice for IDE support and developer clarity.

templates/node/src/models/request_model.ts.twig (1)

10-20: LGTM!

The interface definition correctly handles optional properties, property documentation, and type resolution. The use of escapeKeyword prevents conflicts with TypeScript reserved words.

src/SDK/Language/DotNet.php (4)

195-201: LGTM! Model type resolution is well-structured.

The logic correctly handles both array and single model parameters with proper namespace prefixes. The precedence (checking array['model'] before model) ensures the correct type is resolved.


474-478: LGTM! Request model generation entry follows established patterns.

The new file generation entry is consistent with the existing definition-scope entry and correctly configured for generating request model files.


511-513: LGTM! Filter implementation is clean and consistent.

The propertyType filter follows the established pattern for Twig filters in this class.


526-533: Namespace handling for sub_schema types is intentional and correct.

The distinction between sub_schema types (without namespace prefix) and regular model parameters (with Appwrite.Models. prefix) is by design. sub_schema types are nested models defined within the same spec and generated in the same Appwrite.Models namespace as their parent models, so they don't require the namespace prefix. This differs from method parameters handled by getTypeName(), which may reference external models and thus require full qualification.

src/Spec/Spec.php (4)

21-27: Good practice: using fully qualified global function names.

The use of leading backslashes (e.g., \filter_var, \file_get_contents, \stream_context_create) explicitly references global namespace functions, which is a best practice in namespaced code. This prevents potential conflicts and improves clarity.


48-126: Excellent: adding return type hints to abstract methods.

The addition of explicit return type hints (: string and : array) to all abstract methods significantly improves type safety and enforces contracts for implementing classes. This aligns with modern PHP best practices.


128-133: LGTM! New abstract method for request models.

The new getRequestModels(): array abstract method directly supports the PR's request model feature. The method signature is clear, well-documented, and follows the same pattern as getDefinitions().


144-144: LGTM! Proper use of mixed type for dynamic attribute methods.

The mixed return type on getAttribute (line 144) and the typed parameters on setAttribute (line 171) accurately reflect these methods' dynamic nature. Since attributes can be of any type, mixed is the correct type hint.

Note: This also requires PHP 8.0+ (same verification as Client.php.twig applies).

Also applies to: 171-171

src/Spec/Swagger2.php (3)

12-440: Excellent: implementing return type hints for all methods.

All method signatures now include explicit return type hints (: string, : array) that match the abstract declarations in Spec.php. This strengthens type safety across the implementation.


198-198: LGTM! Adding model reference tracking to body parameters.

Lines 262 and 265 add model fields to capture request model references from body parameters. This enables the template layer to generate properly typed parameters for request models.

Also applies to: 262-265


459-509: LGTM! Clean separation of regular definitions from request models.

The refactored getDefinitions() now properly skips x-request-model definitions (lines 467-469) and enriches properties with metadata needed for template generation. The property processing loop correctly uses null coalescing operators for safe defaults.

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

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9857b94 and a1d5cc7.

📒 Files selected for processing (6)
  • src/SDK/Language/Go.php (2 hunks)
  • templates/dart/base/utils.twig (1 hunks)
  • templates/flutter/base/utils.twig (1 hunks)
  • templates/go/services/service.go.twig (1 hunks)
  • templates/python/package/services/service.py.twig (1 hunks)
  • templates/web/src/models.ts.twig (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/SDK/Language/Go.php (1)
src/SDK/Language.php (1)
  • toPascalCase (116-119)
⏰ 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). (20)
  • GitHub Check: build (8.3, WebChromium)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, Swift56)
  • GitHub Check: build (8.3, PHP80)
  • GitHub Check: build (8.3, Node18)
  • GitHub Check: build (8.3, Python310)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, DotNet60)
  • GitHub Check: build (8.3, Node20)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: build (8.3, Go118)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: build (8.3, DartStable)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, KotlinJava11)
  • GitHub Check: build (8.3, CLINode18)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: swift (server)
  • GitHub Check: apple (client)
  • GitHub Check: android (client)
🔇 Additional comments (7)
templates/python/package/services/service.py.twig (1)

18-23: LGTM! Model import logic follows established patterns.

The conditional import for parameter.model correctly mirrors the existing patterns for enums and InputFile. The duplicate prevention using the added array ensures models are imported only once, and the use of caseSnake and caseUcfirst filters maintains consistency with the codebase conventions.

templates/go/services/service.go.twig (1)

11-13: LGTM! Clean integration with existing import logic.

The conditional check for parameter.model correctly follows the same pattern used for InputFile detection. Setting requireModelsPkg = true appropriately triggers the models package import, maintaining consistency with the template's existing approach.

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

151-155: LGTM!

The new requestModel file generation entry follows the established pattern from the existing definition scope and uses consistent naming conventions (caseSnake filter for the destination filename).


169-175: LGTM!

The type resolution logic correctly handles model-based types:

  • array.model returns a Go slice type []models.X
  • model with array type returns slice, otherwise returns the model type directly

The check order (before items handling at line 176) ensures model-based resolution takes precedence, which aligns with the AI summary's intent.

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

34-47: LGTM! Clean implementation following existing patterns.

The request model generation follows the same structure as the existing definitions block. The optional property handling, schema resolution, and documentation are all correctly implemented.

templates/flutter/base/utils.twig (1)

4-6: LGTM! Consistent with Dart template.

The changes mirror those in templates/dart/base/utils.twig, maintaining consistent handling of model and array.model types across both Dart and Flutter SDK generation. The null-safety logic is correct for Flutter's Dart implementation.

templates/dart/base/utils.twig (1)

4-6: LGTM. Null-safety handling for model and array.model types is correct:

  • Line 4 correctly uses ! assertion after the null-check guard for non-nullable optional parameters
  • Line 6 properly applies ? operator only when parameters are not required
  • The .map((p) => p.toMap()).toList() pattern for arrays and .toMap() for single models generates valid Dart code

Both request_model.dart.twig and model.dart.twig consistently implement toMap() methods, and the abstract Model class enforces this contract across all generated model classes.

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

♻️ Duplicate comments (1)
templates/python/package/models/request_model.py.twig (1)

1-7: Fix pipeline failure: extra blank lines after import loop.

The template still has the formatting issue (H014) flagged in the previous review. When no enum properties are present, extra blank lines appear between imports and the class definition.

🧹 Nitpick comments (2)
templates/python/package/models/request_model.py.twig (1)

32-35: Move json import to module level.

Importing json inside the method is unconventional. Module-level imports improve clarity and follow Python conventions.

Apply this diff to move the import to the top:

 from typing import Optional, List, Dict, Any
+import json
 {%~ for property in requestModel.properties %}
 {%~ if property.enum %}
 from ..enums.{{ property.enumName | caseSnake }} import {{ property.enumName | caseUcfirst }}
 {%~ endif %}
 {%~ endfor %}

 class {{ requestModel.name | caseUcfirst }}:

Then remove it from the method:

     def to_json(self) -> str:
         """Convert the model to a JSON string."""
-        import json
         return json.dumps(self.to_map())
templates/ruby/lib/container/models/request_model.rb.twig (1)

55-57: Consider string interpolation for better Ruby style.

The .to_s call addresses the TypeError risk from the previous review. However, string interpolation is more idiomatic than concatenation with +.

Apply this diff for more idiomatic Ruby:

                 unless valid_{{ property.name | caseSnake }}.include?({{ property.name | caseSnake | escapeKeyword }})
-                    raise ArgumentError, "Invalid " + {{ property.name | caseSnake | escapeKeyword }}.to_s + ". Must be one of: " + valid_{{ property.name | caseSnake }}.join(', ')
+                    raise ArgumentError, "Invalid #{{{ property.name | caseSnake | escapeKeyword }}}. Must be one of: #{valid_{{ property.name | caseSnake }}.join(', ')}"
                 end
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a1d5cc7 and f9e6884.

📒 Files selected for processing (5)
  • templates/node/src/models/request_model.ts.twig (1 hunks)
  • templates/php/src/Client.php.twig (2 hunks)
  • templates/python/package/models/request_model.py.twig (1 hunks)
  • templates/ruby/lib/container/models/request_model.rb.twig (1 hunks)
  • templates/web/src/models.ts.twig (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • templates/php/src/Client.php.twig
  • templates/node/src/models/request_model.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). (20)
  • GitHub Check: build (8.3, PHP80)
  • GitHub Check: build (8.3, Ruby27)
  • GitHub Check: build (8.3, WebChromium)
  • GitHub Check: build (8.3, Ruby30)
  • GitHub Check: build (8.3, WebNode)
  • GitHub Check: build (8.3, AppleSwift56)
  • GitHub Check: build (8.3, Python311)
  • GitHub Check: build (8.3, Android5Java17)
  • GitHub Check: build (8.3, KotlinJava17)
  • GitHub Check: build (8.3, Node16)
  • GitHub Check: build (8.3, KotlinJava8)
  • GitHub Check: build (8.3, Go118)
  • GitHub Check: build (8.3, Go112)
  • GitHub Check: build (8.3, DartStable)
  • GitHub Check: build (8.3, FlutterStable)
  • GitHub Check: build (8.3, FlutterBeta)
  • GitHub Check: build (8.3, Android14Java17)
  • GitHub Check: swift (server)
  • GitHub Check: android (client)
  • GitHub Check: apple (client)
🔇 Additional comments (5)
templates/web/src/models.ts.twig (1)

34-54: LGTM! Past review comment has been fully addressed.

The requestModels block now correctly includes both generics support (line 39) and additionalProperties support (lines 47-53), matching the pattern used in the definitions block (lines 13-33). The implementation maintains consistency across both sections, ensuring request models have the same capabilities as response models.

templates/python/package/models/request_model.py.twig (1)

8-30: LGTM!

The class structure, initialization, and serialization logic are well-implemented with proper type hints, nil checks for nested objects, and correct handling of enums and arrays.

templates/ruby/lib/container/models/request_model.rb.twig (3)

1-1: LGTM!

The frozen string literal comment now has the correct syntax with a space after #.


3-27: LGTM!

The module structure, attr_readers, and initialization logic are well-implemented. The conditional enum validation correctly handles both required and optional properties.


38-63: LGTM!

The to_json delegation, conditional private section, and enum validation methods are correctly implemented with proper error messages.

@abnegate abnegate merged commit 5a14a02 into master Dec 18, 2025
53 checks passed
@abnegate abnegate deleted the feat-request-model branch December 18, 2025 09:15
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