Skip to content

Add type_enum support and update docs#10496

Merged
loks0n merged 8 commits into1.8.xfrom
cursor/add-type-enum-support-and-update-docs-3769
Sep 22, 2025
Merged

Add type_enum support and update docs#10496
loks0n merged 8 commits into1.8.xfrom
cursor/add-type-enum-support-and-update-docs-3769

Conversation

@ChiragAgg5k
Copy link
Copy Markdown
Member

What does this PR do?

This PR adds support for a new TYPE_ENUM in Appwrite's response models. The motivation is to improve API documentation and validation by explicitly defining fields that accept a fixed set of values.

Specifically, this PR:

  • Introduces TYPE_ENUM constant and functionality in the base Model class.
  • Updates 8 existing response models (Attribute, Deployment, Execution, HealthAntivirus, HealthStatus, Index, Platform, Rule) to utilize TYPE_ENUM for relevant fields, providing their possible enum values.
  • Modifies the OpenAPI3 and Swagger2 specification generators to correctly output enum constraints in the generated API specifications for both single and array enum fields.

Test Plan

  1. Verify Model Definitions: Check the updated model files (e.g., src/Appwrite/Utopia/Response/Model/Attribute.php) to ensure type is set to self::TYPE_ENUM and the enum array contains the correct values for the specified fields.
  2. Generate API Specifications: Run the specification generation scripts (e.g., php vendor/bin/appwrite spec openapi3 and php vendor/bin/appwrite spec swagger2) to regenerate the API specifications.
  3. Inspect Generated Specs:
    • Open the generated openapi3.json and swagger2.json files.
    • Search for the updated models and fields (e.g., Attribute.status, Execution.trigger, Deployment.status).
    • Confirm that the enum keyword is present with the correct array of allowed values for these fields in the generated schemas/definitions.
    • For array enum fields (if any were updated), ensure items.enum is correctly applied.

Related PRs and Issues

  • (None)

Checklist

  • Have you read the Contributing Guidelines on issues?
  • If the PR includes a change to an API's metadata (desc, label, params, etc.), does it also include updated API specs and example docs?

Open in Cursor Open in Web

@cursor
Copy link
Copy Markdown

cursor bot commented Sep 15, 2025

Cursor Agent can help with this pull request. Just @cursor in comments and I'll start working on changes in this branch.
Learn more about Cursor Agents

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 15, 2025

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds support for an enum type across the codebase. A new public constant TYPE_ENUM is introduced on the base Model. Multiple response models switch specific fields from TYPE_STRING to TYPE_ENUM and include explicit enum value arrays (Attribute, Deployment, Execution, HealthAntivirus, HealthStatus, Index, Platform, Rule, etc.). OpenAPI3 and Swagger2 formatters are extended to emit enum constraints for scalar and array properties when rules specify enums. GraphQL mapper is updated to treat the enum rule as a string default and adds a case to resolve enum columns via the model prefix (with a comment about dedicated enum types). No public method signatures were changed.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Scope: Many model files plus two API specification formatters and GraphQL mapper.
  • Nature: Repeated declarative changes (model rules) and targeted serializer/mapping logic additions.
  • Complexity: Moderate — verify enum value lists, ensure formatters attach enums correctly for scalar and array fields, and confirm GraphQL mapping behavior aligns with intended enum handling.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The title "Add type_enum support and update docs" succinctly captures the primary change (introducing TYPE_ENUM across models and updating OpenAPI/Swagger output) and is concise, specific, and directly relevant to the changes in the diff.
Description Check ✅ Passed The PR description clearly states the motivation, lists the core changes (new TYPE_ENUM, updated models, and spec generator changes), and provides a sensible test plan that aligns with the provided raw summary and objectives.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch cursor/add-type-enum-support-and-update-docs-3769

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f9bc65 and 31ed726.

📒 Files selected for processing (1)
  • src/Appwrite/GraphQL/Types/Mapper.php (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Appwrite/GraphQL/Types/Mapper.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: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E General Test
  • GitHub Check: Unit Test
  • GitHub Check: Benchmark
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 15, 2025

Security Scan Results for PR

Docker Image Scan Results

Package Version Vulnerability Severity
libexpat 2.7.1-r0 CVE-2025-59375 HIGH
golang.org/x/crypto v0.31.0 CVE-2025-22869 HIGH
golang.org/x/oauth2 v0.24.0 CVE-2025-22868 HIGH
stdlib 1.22.10 CVE-2025-47906 HIGH
stdlib 1.22.10 CVE-2025-47907 HIGH

Source Code Scan Results

🎉 No vulnerabilities found!

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 15, 2025

✨ Benchmark results

  • Requests per second: 1,107
  • Requests with 200 status code: 199,217
  • P99 latency: 0.175100178

⚡ Benchmark Comparison

Metric This PR Latest version
RPS 1,107 895
200 199,217 161,179
P99 0.175100178 0.213807404

@ChiragAgg5k ChiragAgg5k requested a review from Copilot September 15, 2025 04:46
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR introduces TYPE_ENUM support to Appwrite's response models to improve API documentation and validation by explicitly defining fields that accept a fixed set of values.

Key changes include:

  • Adding TYPE_ENUM constant to the base Model class with enum value support
  • Updating 8 response models to use TYPE_ENUM for appropriate fields
  • Modifying OpenAPI3 and Swagger2 generators to output proper enum constraints

Reviewed Changes

Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Appwrite/Utopia/Response/Model.php Adds TYPE_ENUM constant and enum array support to base Model class
src/Appwrite/Utopia/Response/Model/*.php Updates 8 models (Attribute, Deployment, Execution, etc.) to use TYPE_ENUM
src/Appwrite/SDK/Specification/Format/*.php Updates OpenAPI3 and Swagger2 generators to handle enum constraints
src/Appwrite/GraphQL/Types/Mapper.php Adds enum type mapping for GraphQL
app/config/specs/*.json Generated specification files with enum constraints added

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Sep 15, 2025

Open in StackBlitz

npm i https://pkg.pr.new/appwrite/appwrite/@appwrite.io/console@10496

commit: d5d6f9a

@ChiragAgg5k ChiragAgg5k changed the base branch from main to 1.8.x September 15, 2025 04:51
@ChiragAgg5k ChiragAgg5k force-pushed the cursor/add-type-enum-support-and-update-docs-3769 branch from c5b38fa to f9ac0b4 Compare September 15, 2025 04:58
@ChiragAgg5k ChiragAgg5k requested a review from Copilot September 15, 2025 05:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated no new comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

@ChiragAgg5k ChiragAgg5k marked this pull request as ready for review September 15, 2025 05:02
Copy link
Copy Markdown
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

Caution

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

⚠️ Outside diff range comments (1)
src/Appwrite/SDK/Specification/Format/OpenAPI3.php (1)

343-346: 204 responses: remove content, not schema.

OpenAPI 3 uses content; unsetting schema has no effect. This produces invalid/noisy specs for 204.

Apply this diff:

-                if (($response->getCode() ?? 500) === 204) {
-                    $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content';
-                    unset($temp['responses'][(string)$response->getCode() ?? '500']['schema']);
-                }
+                if (($response->getCode() ?? 500) === 204) {
+                    $temp['responses'][(string)$response->getCode() ?? '500']['description'] = 'No content';
+                    unset($temp['responses'][(string)$response->getCode() ?? '500']['content']);
+                }
♻️ Duplicate comments (2)
src/Appwrite/Utopia/Response/Model/HealthAntivirus.php (1)

20-25: Enum-ify status + grammar fix: looks good.

This resolves the prior grammar note.

src/Appwrite/Utopia/Response/Model/HealthStatus.php (1)

26-31: Enum-ify status + grammar fix LGTM.

Switching to TYPE_ENUM with ['pass','fail'] and fixing the description matches prior feedback.

🧹 Nitpick comments (9)
src/Appwrite/Utopia/Response/Model/Rule.php (2)

56-60: Integer default set to empty string.

redirectStatusCode is integer but has default ''. Recommend numeric default (e.g., 301) to avoid type drift in responses.

-            ->addRule('redirectStatusCode', [
-                'type' => self::TYPE_INTEGER,
-                'description' => 'Status code to apply during redirect. Used if type is "redirect"',
-                'default' => '',
-                'example' => 301,
-            ])
+            ->addRule('redirectStatusCode', [
+                'type' => self::TYPE_INTEGER,
+                'description' => 'Status code to apply during redirect. Used if type is "redirect"',
+                'default' => 301,
+                'example' => 301,
+            ])

80-85: Example value seems wrong.

deploymentVcsProviderBranch example should be a branch name, not "function".

-                'example' => 'function',
+                'example' => 'main',
src/Appwrite/Utopia/Response/Model/Execution.php (1)

81-86: requestHeaders description references response headers.

Minor doc mismatch; adjust to “HTTP request headers…”.

-            ->addRule('requestHeaders', [
-                'type' => Response::MODEL_HEADERS,
-                'description' => 'HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.',
+            ->addRule('requestHeaders', [
+                'type' => Response::MODEL_HEADERS,
+                'description' => 'HTTP request headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.',
src/Appwrite/SDK/Specification/Format/Swagger2.php (1)

799-805: Emit enum values for models — correct.

Scalar vs array handling is right. Optional: consider emitting x-enum-name/x-enum-keys for model enums to align with parameter enums and help SDKs.

src/Appwrite/Utopia/Response/Model/Deployment.php (1)

134-139: Duplicate rule key: providerBranch defined twice.

Second definition overwrites the first in $this->rules. Drop the duplicate.

-            ->addRule('providerBranch', [
-                'type' => self::TYPE_STRING,
-                'description' => 'The branch of the vcs repository',
-                'default' => '',
-                'example' => '0.7.x',
-            ])

Also applies to: 170-175

src/Appwrite/SDK/Specification/Format/OpenAPI3.php (3)

685-688: Enum mapped to string: confirm all enums are strings (optionally infer type).

Today all added enums appear to be strings, so mapping to 'string' is fine. If we ever introduce numeric/boolean enums, consider inferring the OpenAPI type from the enum values to avoid incorrect typing.

Apply this diff if you want lightweight inference:

-                case 'enum':
-                    $type = 'string';
-                    break;
+                case 'enum':
+                    $type = 'string';
+                    if (!empty($rule['enum'])) {
+                        $allInts = array_reduce($rule['enum'], fn($c, $v) => $c && is_int($v), true);
+                        $allNums = $allInts || array_reduce($rule['enum'], fn($c, $v) => $c && is_numeric($v), true);
+                        $allBools = array_reduce($rule['enum'], fn($c, $v) => $c && is_bool($v), true);
+                        if ($allBools) {
+                            $type = 'boolean';
+                        } elseif ($allInts) {
+                            $type = 'integer';
+                            $format = 'int32';
+                        } elseif ($allNums) {
+                            $type = 'number';
+                            $format = 'float';
+                        } else {
+                            $type = 'string';
+                        }
+                    }
+                    break;

777-783: Emit enum lists (good); dedupe for deterministic specs.

Emitting enum at the correct location is right. Minor: de-duplicate values to keep specs stable if upstream lists contain dupes.

Apply this diff:

-                if ($rule['type'] === 'enum' && !empty($rule['enum'])) {
+                if ($rule['type'] === 'enum' && !empty($rule['enum'])) {
+                    $enumValues = array_values(array_unique($rule['enum']));
                     if ($rule['array']) {
-                        $output['components']['schemas'][$model->getType()]['properties'][$name]['items']['enum'] = $rule['enum'];
+                        $output['components']['schemas'][$model->getType()]['properties'][$name]['items']['enum'] = $enumValues;
                     } else {
-                        $output['components']['schemas'][$model->getType()]['properties'][$name]['enum'] = $rule['enum'];
+                        $output['components']['schemas'][$model->getType()]['properties'][$name]['enum'] = $enumValues;
                     }
                 }

297-305: Typo: incorrect SVG media type.

Use image/svg+xml instead of image/svg-x.

Apply this diff:

-                            'image/svg-x',
+                            'image/svg+xml',
src/Appwrite/Utopia/Response/Model/Platform.php (1)

61-65: Example type mismatch: hostname example is boolean, should be string.

'type' => self::TYPE_STRING but 'example' => true.

Apply this diff:

-            ->addRule('hostname', [
+            ->addRule('hostname', [
                 'type' => self::TYPE_STRING,
                 'description' => 'Web app hostname. Empty string for other platforms.',
                 'default' => '',
-                'example' => true,
+                'example' => 'app.example.com',
             ])
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2fb9350 and 0f5cb26.

⛔ Files ignored due to path filters (12)
  • app/config/specs/open-api3-1.8.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
📒 Files selected for processing (11)
  • src/Appwrite/SDK/Specification/Format/OpenAPI3.php (2 hunks)
  • src/Appwrite/SDK/Specification/Format/Swagger2.php (2 hunks)
  • src/Appwrite/Utopia/Response/Model.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Attribute.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Deployment.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Execution.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/HealthAntivirus.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/HealthStatus.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Index.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Platform.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Rule.php (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
src/Appwrite/SDK/Specification/Format/Swagger2.php (1)
src/Appwrite/Utopia/Response.php (1)
  • output (738-820)
src/Appwrite/SDK/Specification/Format/OpenAPI3.php (2)
src/Appwrite/Utopia/Response.php (1)
  • output (738-820)
src/Appwrite/GraphQL/Types/Mapper.php (1)
  • model (175-242)
src/Appwrite/Utopia/Response/Model/Execution.php (1)
src/Appwrite/Utopia/Response/Model.php (1)
  • addRule (90-102)
⏰ 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: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Migrations)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Functions)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Unit Test
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (11)
src/Appwrite/Utopia/Response/Model/Index.php (1)

44-49: Enum-ify status: good change.

Enum values match description; generation should emit items correctly in specs.

src/Appwrite/Utopia/Response/Model/Rule.php (3)

68-73: deploymentResourceType enum: good.


75-79: Grammar fix in description.
[ suggest_nitpick_refactor ]

-                'description' => 'ID deployment\'s resource. Used if type is "deployment"',
+                'description' => 'ID of the deployment resource. Used if type is "deployment"',

94-98: Typo in example.
[ suggest_nitpick_refactor ]

-                'example' => 'HTTP challegne failed.',
+                'example' => 'HTTP challenge failed.',
src/Appwrite/Utopia/Response/Model/Attribute.php (1)

26-31: Enum-ify status: looks good.

src/Appwrite/Utopia/Response/Model/Execution.php (2)

55-60: Enum-ify trigger: looks good.


62-67: Enum-ify status: looks good.

src/Appwrite/SDK/Specification/Format/Swagger2.php (1)

693-696: Swagger2: map enum to string type — correct.

src/Appwrite/Utopia/Response/Model/Deployment.php (1)

98-103: Enum-ify status: looks good.

src/Appwrite/Utopia/Response/Model.php (1)

19-19: Approve: TYPE_ENUM added — OpenAPI3 handles enum.
Found "case 'enum'" in src/Appwrite/SDK/Specification/Format/OpenAPI3.php:685.

src/Appwrite/Utopia/Response/Model/Platform.php (1)

43-48: Platform.type: enum conversion looks good.

Allowed values align with the description; OpenAPI/Swagger emitters will now constrain this field.

Copy link
Copy Markdown
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

🧹 Nitpick comments (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)

62-63: Consider using a more type-safe default for enum fields.

While Type::string() works as a fallback, consider whether Type::string() is the most appropriate default for enum types. Since enums represent a constrained set of values, you might want to either:

  1. Throw an exception if an enum type is used without enum values
  2. Use a more restrictive type or validation
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f5cb26 and 40eaf39.

📒 Files selected for processing (1)
  • src/Appwrite/GraphQL/Types/Mapper.php (5 hunks)
⏰ 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: E2E Service Test (Webhooks)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (Tokens)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Console)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Avatars)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: Unit Test
  • GitHub Check: E2E General Test
  • GitHub Check: Benchmark
  • GitHub Check: Setup & Build SDK
  • GitHub Check: scan
🔇 Additional comments (3)
src/Appwrite/GraphQL/Types/Mapper.php (3)

9-9: LGTM! Clean import addition for enum support.

The EnumType import is correctly placed with other GraphQL type imports and follows the existing code organization pattern.


394-416: Well-structured enum type creation with proper caching.

The implementation correctly:

  • Creates unique enum type names per field
  • Implements caching to avoid duplicate type creation
  • Sanitizes enum values for GraphQL compatibility
  • Maintains original values in the GraphQL schema

491-491: Confirmed: AttributeEnum and ColumnEnum models exist.
Found src/Appwrite/Utopia/Response/Model/AttributeEnum.php (class AttributeEnum extends Attribute) and src/Appwrite/Utopia/Response/Model/ColumnEnum.php (class ColumnEnum extends Column).

Comment on lines +403 to +407
foreach ($rule['enum'] as $enumValue) {
$values[\strtoupper(\str_replace(['-', ' ', '.'], '_', $enumValue))] = [
'value' => $enumValue
];
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider additional character replacements for GraphQL enum value names.

The current implementation replaces -, , and . with underscores. However, GraphQL enum values have strict naming requirements and other special characters might cause issues.

Consider using a more comprehensive sanitization approach:

 foreach ($rule['enum'] as $enumValue) {
-    $values[\strtoupper(\str_replace(['-', ' ', '.'], '_', $enumValue))] = [
+    // GraphQL enum values must match [_A-Za-z][_0-9A-Za-z]*
+    $sanitizedKey = \preg_replace('/[^A-Za-z0-9_]/', '_', $enumValue);
+    $sanitizedKey = \preg_replace('/^[0-9]/', '_$0', $sanitizedKey); // Prefix number with underscore
+    $values[\strtoupper($sanitizedKey)] = [
         'value' => $enumValue
     ];
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
foreach ($rule['enum'] as $enumValue) {
$values[\strtoupper(\str_replace(['-', ' ', '.'], '_', $enumValue))] = [
'value' => $enumValue
];
}
foreach ($rule['enum'] as $enumValue) {
// GraphQL enum values must match [_A-Za-z][_0-9A-Za-z]*
$sanitizedKey = \preg_replace('/[^A-Za-z0-9_]/', '_', $enumValue);
$sanitizedKey = \preg_replace('/^[0-9]/', '_$0', $sanitizedKey); // Prefix number with underscore
$values[\strtoupper($sanitizedKey)] = [
'value' => $enumValue
];
}
🤖 Prompt for AI Agents
In src/Appwrite/GraphQL/Types/Mapper.php around lines 403 to 407, the enum name
sanitization only replaces '-', ' ', and '.' which can leave other invalid
characters for GraphQL enum identifiers; update the sanitizer to replace any
non-alphanumeric/underscore character with an underscore, collapse consecutive
underscores, trim leading/trailing underscores, ensure the identifier does not
start with a digit (prefix with an underscore if it does), convert to
upper-case, and provide a safe fallback name if the result is empty so all
generated enum keys are valid GraphQL identifiers.

💡 Verification agent

🧩 Analysis chain

Verify handling of duplicate enum keys after sanitization.

After sanitizing enum values (converting to uppercase and replacing characters), there's a risk of key collisions. For example, "foo-bar" and "foo.bar" would both become "FOO_BAR".


🏁 Script executed:

#!/bin/bash
# Search for enum definitions in model files to check for potential collisions
echo "Searching for enum arrays in Model files..."
rg -A 5 "TYPE_ENUM.*enum.*=>" src/Appwrite/Utopia/Response/Model/ --type php

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Check if there are any enum values that could cause collisions after sanitization
echo "Checking for potential enum value collisions..."
ast-grep --pattern 'enum => [$$$]' --lang php | head -20

Length of output: 289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "PWD: $(pwd)"
echo "Looking for the file mentioned in the review..."
if [ -f src/Appwrite/GraphQL/Types/Mapper.php ]; then
  echo "FOUND: src/Appwrite/GraphQL/Types/Mapper.php"
  echo "---- Mapper.php (lines 360-440) ----"
  sed -n '360,440p' src/Appwrite/GraphQL/Types/Mapper.php || true
  echo "---- Mapper.php (full file head) ----"
  sed -n '1,240p' src/Appwrite/GraphQL/Types/Mapper.php || true
else
  echo "src/Appwrite/GraphQL/Types/Mapper.php not found"
fi

echo
echo "Searching repository for occurrences of enum definitions and the problematic pattern..."
rg -n --hidden --no-ignore "'enum'\s*=>" --type php -S || true
rg -n "foreach\s*\(\s*\$rule\['enum'\]\s*as" -S || true
rg -n "strtoupper\(\s*\\?str_replace" -S || true
rg -n "strtoupper\(|str_replace\(" -S || true

echo
echo "Listing files under src/Appwrite to help locate Model definitions (first 200 lines)..."
ls -la src/Appwrite | sed -n '1,200p' || true

Length of output: 62487


🏁 Script executed:

#!/bin/bash
set -euo pipefail
echo "Scanning src/Appwrite/Utopia/Response/Model for enum arrays and computing sanitized keys..."

python3 - <<'PY'
import os, re, sys, json
root = "src/Appwrite/Utopia/Response/Model"
if not os.path.isdir(root):
    print("Directory not found:", root)
    sys.exit(0)

sanitized_map = {}  # key -> list of (file, original)
file_enum_map = {}

php_string_re = re.compile(r"""('([^'\\]*(?:\\.[^'\\]*)*)'|"([^"\\]*(?:\\.[^"\\]*)*)")""", re.S)

for fname in sorted(os.listdir(root)):
    if not fname.endswith(".php"):
        continue
    path = os.path.join(root, fname)
    with open(path, "r", encoding="utf-8") as f:
        src = f.read()
    # find occurrences of "'enum' => ["
    for m in re.finditer(r"(['\"])enum\1\s*=>\s*\[", src):
        start = m.end() - 1  # position of '['
        i = start
        depth = 0
        end = None
        while i < len(src):
            ch = src[i]
            if ch == '[':
                depth += 1
            elif ch == ']':
                depth -= 1
                if depth == 0:
                    end = i
                    break
            i += 1
        if end is None:
            continue
        arr_text = src[start+1:end]  # inside brackets
        # find string literals inside arr_text
        values = []
        for sm in php_string_re.finditer(arr_text):
            s = sm.group(2) if sm.group(2) is not None else sm.group(3)
            # unescape simple escapes
            s = s.encode('utf-8').decode('unicode_escape')
            values.append(s)
        if not values:
            continue
        file_enum_map.setdefault(path, []).append(values)
        for v in values:
            key = v.replace('-', '_').replace(' ', '_').replace('.', '_').upper()
            sanitized_map.setdefault(key, []).append((path, v))

# Print per-file enums
print("Found enum arrays in files:")
for path, enums in file_enum_map.items():
    for idx, vals in enumerate(enums,1):
        print(f"- {path} (enum #{idx}): {vals}")

# Detect sanitized collisions
collisions = {k: v for k, v in sanitized_map.items() if len(v) > 1}
if not collisions:
    print("\nNo sanitized-key collisions detected across enum values.")
else:
    print("\nSanitized-key COLLISIONS detected:")
    for k, items in collisions.items():
        print(f"\nKEY: {k}")
        for path, val in items:
            print(f"  - {path}: '{val}'")
    print("\nTotal collision keys:", len(collisions))

# For completeness, print total counts
total_enum_values = sum(len(v) for v in sanitized_map.values())
print(f"\nTotal distinct sanitized keys: {len(sanitized_map)}")
print(f"Total enum value occurrences scanned: {total_enum_values}")
PY

Length of output: 2436


🏁 Script executed:

#!/bin/bash
set -euo pipefail

files=(
  src/Appwrite/Utopia/Response/Model/Attribute.php
  src/Appwrite/Utopia/Response/Model/Deployment.php
  src/Appwrite/Utopia/Response/Model/Execution.php
  src/Appwrite/Utopia/Response/Model/HealthAntivirus.php
  src/Appwrite/Utopia/Response/Model/HealthStatus.php
  src/Appwrite/Utopia/Response/Model/Index.php
  src/Appwrite/Utopia/Response/Model/Platform.php
  src/Appwrite/Utopia/Response/Model/Rule.php
)

for f in "${files[@]}"; do
  if [ -f "$f" ]; then
    echo "---- $f ----"
    rg -n -C3 "'enum'\s*=>" "$f" || true
    echo "---- full file preview ----"
    sed -n '1,240p' "$f" || true
    echo
  else
    echo "MISSING: $f"
  fi
done

Length of output: 35066


Fix enum key collisions and shared enum types in Mapper::createEnumType

  • Issue: createEnumType maps enum values to keys via strtoupper/str_replace and names enum types using only the field name (ucfirst($fieldName) . 'Enum'), so different models' fields (e.g., multiple "status" fields) share the same GraphQL Enum and can overwrite/mismatch values depending on processing order. Scan found status enums in Attribute, Index, Deployment, Execution, Rule and sanitized-key collisions: AVAILABLE, PROCESSING, DELETING, STUCK, FAILED, WAITING.
  • Action: make enum type names unique per model (e.g., include the model/type: ucfirst($modelName).ucfirst($fieldName).'Enum') or otherwise namespace them; and in the value-generation loop detect/resolve duplicate sanitized keys (throw CI error or append deterministic suffix) instead of silently overwriting. Update Registry usage so enums are not silently reused across distinct model enums.
  • Location: src/Appwrite/GraphQL/Types/Mapper.php (createEnumType ~lines 403–407). Related files: src/Appwrite/Utopia/Response/Model/{Attribute.php, Index.php, Deployment.php, Execution.php, Rule.php}.

Copy link
Copy Markdown
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

🧹 Nitpick comments (1)
src/Appwrite/GraphQL/Types/Mapper.php (1)

62-64: Consider removing default registry mapping for 'enum'

You already create real GraphQL EnumTypes for model enum rules. Keeping 'enum' => Type::string() as a default may hide misconfigurations (e.g., missing enum list) by silently falling back to string.

-            'array' => Types::json(),
-            'enum' => Type::string()
+            'array' => Types::json()
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0f5cb26 and ef69520.

⛔ Files ignored due to path filters (12)
  • app/config/specs/open-api3-1.8.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/open-api3-latest-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-1.8.x-server.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-client.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-console.json is excluded by !app/config/specs/**
  • app/config/specs/swagger2-latest-server.json is excluded by !app/config/specs/**
📒 Files selected for processing (5)
  • src/Appwrite/GraphQL/Types/Mapper.php (5 hunks)
  • src/Appwrite/Utopia/Response/Model/Deployment.php (1 hunks)
  • src/Appwrite/Utopia/Response/Model/Execution.php (2 hunks)
  • src/Appwrite/Utopia/Response/Model/Platform.php (2 hunks)
  • src/Appwrite/Utopia/Response/Model/Rule.php (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Appwrite/Utopia/Response/Model/Execution.php
  • src/Appwrite/Utopia/Response/Model/Rule.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). (19)
  • GitHub Check: E2E Service Test (VCS)
  • GitHub Check: E2E Service Test (Account)
  • GitHub Check: E2E Service Test (Messaging)
  • GitHub Check: E2E Service Test (Users)
  • GitHub Check: E2E Service Test (Teams)
  • GitHub Check: E2E Service Test (Locale)
  • GitHub Check: E2E Service Test (Storage)
  • GitHub Check: E2E Service Test (Realtime)
  • GitHub Check: E2E Service Test (Sites)
  • GitHub Check: E2E Service Test (Projects)
  • GitHub Check: E2E Service Test (Proxy)
  • GitHub Check: E2E Service Test (GraphQL)
  • GitHub Check: E2E Service Test (Health)
  • GitHub Check: E2E Service Test (Databases/TablesDB)
  • GitHub Check: E2E Service Test (FunctionsSchedule)
  • GitHub Check: E2E Service Test (Databases/Legacy)
  • GitHub Check: E2E Service Test (Site Screenshots)
  • GitHub Check: E2E Service Test (Dev Keys)
  • GitHub Check: Benchmark
🔇 Additional comments (3)
src/Appwrite/Utopia/Response/Model/Platform.php (1)

65-65: Hostname example fix: LGTM

src/Appwrite/GraphQL/Types/Mapper.php (2)

9-9: EnumType import: LGTM


491-491: Resolved — AttributeEnum and ColumnEnum models exist; no change required.

AttributeEnum and ColumnEnum classes found at src/Appwrite/Utopia/Response/Model/AttributeEnum.php and src/Appwrite/Utopia/Response/Model/ColumnEnum.php; static::model("{$prefix}Enum") is valid.

@loks0n loks0n self-requested a review September 16, 2025 10:06
Copy link
Copy Markdown

@Aglowharmony Aglowharmony left a comment

Choose a reason for hiding this comment

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

Clean af
merge this

Comment on lines -133 to -138
->addRule('providerBranch', [
'type' => self::TYPE_STRING,
'description' => 'The branch name of the vcs provider repository',
'default' => '',
'example' => 'main',
])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why do we remove this?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Screenshot 2025-09-22 at 4 57 02 PM

its duplicated

@loks0n loks0n merged commit ab7d3d3 into 1.8.x Sep 22, 2025
43 checks passed
@stnguyen90 stnguyen90 deleted the cursor/add-type-enum-support-and-update-docs-3769 branch October 1, 2025 23:57
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.

4 participants