Skip to content

Add Godot platform support and GDScript SDK generator#1527

Open
NIKHIL0VERMA wants to merge 54 commits into
appwrite:masterfrom
NIKHIL0VERMA:feat/godot-support
Open

Add Godot platform support and GDScript SDK generator#1527
NIKHIL0VERMA wants to merge 54 commits into
appwrite:masterfrom
NIKHIL0VERMA:feat/godot-support

Conversation

@NIKHIL0VERMA
Copy link
Copy Markdown

@NIKHIL0VERMA NIKHIL0VERMA commented May 11, 2026

What does this PR do?

This PR adds support for the Godot game engine and introduces GDScript as a new SDK generation target.

The generated SDK is designed for Godot 4.x projects and enables direct integration with Appwrite services using GDScript

Godot-specific implementation details

  • Used a global Appwrite autoload singleton to expose services in a more idiomatic Godot-style API instead of requiring separate exports/imports for every service
  • Some method names are changed to handle GDScript keyword conflicts. For example:
    • Appwrite.account.get() conflicts with a built-in GDScript method
    • Replaced with Appwrite.account.xget()

The generated SDK is designed for Godot 4.x projects and enables direct integration with Appwrite services using GDScript.

Test Plan

The Godot SDK generates with sample project which can be opened directly inside the Godot Engine for integration testing.

The generated project also includes test files compatible with the GUT testing framework. Tests can be executed after installing GUT from the Godot Asset Library. If GUT is not installed, parsing error of test files can be ignored safely.

Automated validation

Added CI and automated SDK validation for generated Godot and GDScript targets.

Personally tested on:

  • Ubuntu 22.04
  • Kernel: 6.5.0-45-generic
  • Godot Engine: 4.6.2.stable.official.71f334935

Verified:

  • Client initialization
  • ping requests
  • Anonymous account creation
  • Email/password account creation
  • Email/password login
  • Logout current session
  • Account session persistence
  • Database CRUD operations
  • Storage CRUD operations
  • Multipart file uploads
  • Large file upload (>5mb)
  • Async request handling
  • Error handling
  • JSON response parsing and serialization

Have you read the Contributing Guidelines on issues?

yes

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 11, 2026

Greptile Summary

This PR introduces two new SDK generation targets — Godot (client, with browser OAuth via a local TCP server and cookie-based session persistence) and GDScript (server, headless redirect-based OAuth) — along with Twig templates, PHP language classes, CI jobs, and integration tests. A large number of issues flagged in the prior review round appear to have been addressed: the oauth_client node is now freed, _call_web routes through _handle_response, ping() properly wraps errors, the nested model prefix is applied, the null-check guard is in appwrite.gd.twig, the multipart boundary is only written after the emptiness check passes, and JavaScriptBridge/OS.has_feature('web') are now used.

  • The GDScript client's request_raw transport failure still returns {\"statusCode\": 400, \"body\": \"...\"} instead of the {\"statusCode\": 0, \"error\": \"...\"} contract every other network-level error uses, causing _handle_response to misclassify a connection failure as a server 400.
  • The JavaScriptBridge.eval() call in oauth2.gd.twig embeds auth_url inside a single-quoted JS string via plain .replace(), which is fragile if the URL ever contains a ' character.
  • When extract_callback_url returns an error dict (malformed HTTP request to the callback server), the \"error\" message is overwritten with statusCode: 401 and then silently discarded by _handle_response, leaving the caller with an AppwriteException with an empty message.

Confidence Score: 4/5

The PR can be merged once the request_raw error-response inconsistency in the GDScript client is resolved; the OAuth and persistence paths are mostly correct.

The GDScript client misclassifies a transport-level failure (e.g., connection refused) as a server HTTP 400 instead of a network error, making it impossible for callers to distinguish between the two. This is the only blocking defect found; the many issues from the prior review round appear to have been addressed.

templates/gdscript/addons/utils/client.gd.twig (the request_raw error-path) and templates/godot/addons/utils/oauth2.gd.twig (the JS string embedding and error-message discard) deserve a close look before merge.

Important Files Changed

Filename Overview
src/SDK/Language/GDScript.php New language class for GDScript SDK generation; getParamDefault returns non-null zero-values for optional params (service template uses Variant = null to work around this), and TYPE_FILE defaults to null correctly via the default: branch.
src/SDK/Language/Godot.php Thin subclass of GDScript with a full getFiles() override adding OAuth2, persistence (cookie), menu scene, and editor config outputs; structure looks correct.
templates/gdscript/addons/utils/client.gd.twig Core HTTP client template; request_raw transport failure returns {"statusCode": 400, "body": "..."} while every other network-level error uses {"statusCode": 0, "error": "..."}, causing incorrect error classification in _handle_response.
templates/godot/addons/utils/client.gd.twig Godot client with cookie persistence and OAuth delegation; oauth_client.queue_free() is now called after authenticate() returns, fixing the previously reported node leak.
templates/godot/addons/utils/oauth2.gd.twig TCP-server OAuth callback implementation; now correctly uses JavaScriptBridge and OS.has_feature('web'), but the JavaScriptBridge.eval() call embeds auth_url inside a single-quoted JS string using plain .replace(), which breaks if the URL ever contains a '. Error messages from malformed callback requests are also silently discarded.
templates/gdscript/addons/models/model.gd.twig Model generation template; nested model and array-of-model references now correctly use the SDK title prefix (e.g., AppwriteTeam), and null-value guard before m.set() prevents typed-property errors.
templates/gdscript/addons/services/service.gd.twig Service generation template; optional parameters correctly typed as Variant = null, float type check now also accepts int via TYPE_INT guard, and Dictionary body check before from_dict is present.
tests/GDScript4Test.php CI test class for GDScript SDK; includes OAUTH_RESPONSES in expected output and uses barichello/godot-ci:4.6 Docker image for headless execution.
tests/Godot4Test.php CI test class for Godot SDK; deliberately omits OAUTH_RESPONSES (confirmed intentional — headless CI cannot run the browser/TCPServer OAuth flow).
templates/godot/addons/persistence/cookie_store.gd.twig Cookie persistence layer for Godot client; correctly handles expiry on load and save, and uses FileAccess (RefCounted) so the file handle is automatically released when the local var goes out of scope.

Reviews (21): Last reviewed commit: "refract: statusCode set to 0 for network..." | Re-trigger Greptile

Comment thread src/SDK/Language/GDScript.php
Comment thread src/SDK/Language/GDScript.php
Comment thread src/SDK/Language/GDScript.php
Comment thread src/SDK/Language/GDScript.php
Comment thread src/SDK/Language/GDScript.php
Comment thread src/SDK/Language/Godot.php Outdated
Comment thread src/SDK/Language/GDScript.php
Comment thread templates/godot/addons/utils/client.gd.twig
Comment thread templates/gdscript/addons/models/model.gd.twig
Comment thread templates/godot/addons/utils/client.gd.twig
@NIKHIL0VERMA NIKHIL0VERMA marked this pull request as draft May 11, 2026 17:24
@NIKHIL0VERMA NIKHIL0VERMA marked this pull request as ready for review May 12, 2026 16:00
Comment thread templates/godot/addons/input_file.gd.twig Outdated
@NIKHIL0VERMA NIKHIL0VERMA marked this pull request as draft May 19, 2026 15:08
Initial implementation of Godot support:
- template-based generation for services and client
- preliminary docs example template
- mirrors structure of existing SDKs (services/, enums/, models/)
- not fully functional yet (runtime + DX pending)
- Refactored Godot SDK output directory structure to follow the addons/appwrite convention for plugins.
- Migrated call_api in client.gd from an HTTPClient polling loop to a native, async HTTPRequest node architecture.
- Added appwrite.gd plugin singleton and updated plugin.cfg / plugin.gd generation logic.
- Implemented robust error handling by parsing HTTP responses into typed AppwriteExceptions.
- Fixed docs/example.md.twig template for correct GDScript method invocation and autoload reference.
- Enhanced global state management by defaulting endpoint and project settings directly from ProjectSettings overrides.
- corrected type resolution for models, enums, arrays of models, and arrays of enums
- added .env support for loading client configuration
- reduced global namespace pollution by removing class_name from enums
- improved enum system to support string-based values (Appwrite-compatible vs Godot int enums)
- refactored models to use FIELD_MAP for better readability and mapping
- added proper import handling for enums and nested models
- updated plugin to load only when enabled (not immediately after installation)
- centralized network calls and exception handling for better debugging
- removed deprecated and duplicate methods from generated services
- updated services to use centralized network caller
- Fix enum handling to use String-based representation instead of invalid typed enums(Godot internal use int representation)
- Resolve incorrect default value mapping for integer parameters (e.g. [] assigned to int in storage)
- Improve parameter type inference in codegen for arrays, enums, and primitives
- Fix Godot HTTPRequest lifecycle issue caused by calling request before node enters scene tree
- Replace deferred node attachment pattern with proper add_child timing
- Improve robustness of generated GDScript service methods and parameter defaults
- refactor Appwrite singleton to delegate all config to client
- centralize environment variable handling with _apply_env()
- add dynamic header setters using spec.global.headers
- support additional env configs (JWT, session, locale, mode, self-signed)
- enforce single client instance via autoload (singleton pattern)
- cleared Appwrite singleton namespace by removing raw classes
Changed typed return values to Variant so errors can be returned to the SDK user instead of causing runtime failures in services.
- Generate inline documentation for all service methods
- Add parameter description using [param] annotation
- Include return type details helping in better type casting
- Automatically annotate deprecated APIs with @deprecated
- Format docs using Godot BBCode for editor integration
- Add explicit typing for services to enable autocomplete and navigation
- Replace inline preload().new() with typed constants and instances
- Introduce class_name to enable doc indexing
- Fix missing method hints for chained calls (e.g., Appwrite.account.*)
- Add description for services and examples
- Exposed Enums through Appwrite autoload
- Ensure documentation appears in editor tooltips along with method hints
- Added Appwrite icon to Godot generated docs
…ethods

- Updated service templates to use 'Variant = null' for all optional parameters.
- Added runtime type validation to ensure passed values match the intended types.
- Included explicit type hints in documentation comments using [Type] notation.
Comment thread templates/gdscript/addons/appwrite.gd.twig
- route ping() through service error handling
- return AppwriteException consistently on failures
- avoid malformed multipart CRLF for empty arrays
- clean up remaining GDScript generator issues
Comment thread templates/godot/addons/utils/oauth2.gd.twig
Comment thread templates/godot/addons/utils/oauth2.gd.twig
Comment thread templates/gdscript/addons/utils/input_file.gd.twig Outdated
Comment thread templates/gdscript/addons/services/service.gd.twig
Comment thread tests/languages/godot/test.gd
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 20, 2026

Want your agent to iterate on Greptile's feedback? Try greploops.

Comment thread templates/godot/addons/utils/client.gd.twig
Comment thread templates/godot/addons/utils/service.gd.twig Outdated
Comment thread templates/gdscript/addons/utils/client.gd.twig
Comment thread templates/gdscript/addons/utils/client.gd.twig
Comment thread templates/gdscript/addons/appwrite.gd.twig
Comment thread templates/gdscript/addons/models/model.gd.twig
Comment thread templates/godot/addons/utils/oauth2.gd.twig
Comment thread templates/gdscript/addons/utils/service.gd.twig Outdated
Comment thread templates/gdscript/addons/utils/client.gd.twig
Comment thread templates/gdscript/addons/utils/client.gd.twig
Comment thread templates/gdscript/addons/utils/client.gd.twig Outdated
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.

1 participant