feat: Unity client SDK (continuation of #1105)#1516
feat: Unity client SDK (continuation of #1105)#1516ChiragAgg5k wants to merge 139 commits intomasterfrom
Conversation
Moved Unity SDK template files from 'templates/unity/Runtime' and 'templates/unity/Editor' to 'templates/unity/Assets/Runtime' and 'templates/unity/Assets/Editor' for better alignment with Unity project conventions. Updated getFiles() in Unity.php to reflect new paths and added support for copying plugin DLLs and project settings. Improved file upload logic in Client.cs.twig to handle streams and byte arrays more robustly, and removed Unity-specific logging from Exception.cs.twig. Minor fixes in Realtime.cs.twig and Role.cs.twig for namespace and async handling.
Introduces Unity2021 test support by adding a Unity2021Test.php, Unity test source files, and updating the GitHub Actions workflow to include Unity2021 in the test matrix and set the UNITY_LICENSE environment variable. This enables automated testing for the Unity SDK within the CI pipeline.
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Introduce centralized property conversion and mapping helpers for the .NET SDK generator and update model template to use them. Changes: - Add Twig filters: propertyAssignment and toMapValue. - Make getPropertyType optionally return non-fully-qualified names. - Replace inline parsing logic with new methods: getPropertyName, getResolvedPropertyName, getPropertyAssignment, convertValue, getToMapExpression. These handle enums, sub-schemas, arrays, primitive conversions and null-safety in a unified way. - Simplify getFunctions() implementation to delegate to the new helpers. - Update templates/dotnet/Package/Models/Model.cs.twig to use the new filters (propertyAssignment, toMapValue) and clean up From/ToMap generation. Reason: centralizes and standardizes property (de)serialization logic, improves null handling, supports property overrides, and simplifies the model template.
Add query support and improve realtime subscription handling; refactor Channel API to use nullable IDs and introduce IChannelValue. - Realtime: support per-subscription queries, normalize channel/query inputs, track subscription slot ↔ id mappings, route messages by subscription id when present, and include queries in websocket URL. Handle pending socket rebuilds and populate subscription maps on connect. - Channel: change Normalize to accept null, use null as default for ID parameters instead of "*", add IChannelValue interface and make IActionable inherit it, remove old Function.Execution pattern and expose Function/Execution as channel values. Add Account/Documents/Rows/Files/Executions/Teams/Memberships helpers. - Tests: add helper WaitForRealtimeMessage and update realtime and Channel-related test calls to match the new APIs. These changes enable more flexible realtime queries and simplify channel construction semantics.
# Conflicts: # templates/dotnet/Package/Models/Model.cs.twig
Greptile SummaryThis PR continues and merges community PR #1105, adding a complete Unity client SDK to the generator — including a
Confidence Score: 3/5Several open defects across the core HTTP client and realtime templates would cause data corruption or silent auth failures in production. The chunked-upload bytes path sends one byte fewer than the Content-Range header declares, corrupting every multi-chunk upload for that source type. The stream ReadAsync is not guarded against partial reads, padding the final chunk with stale buffer bytes. The realtime connected-message handler accesses data.User without a null guard after using data?.Subscriptions one line above, silently skipping fallback authentication when data is null. The cookie header is written to Debug.Log in plain text on every non-WebGL request. The UNITY_TEST_MODE global leaks across tests, and getPropertyAssignment defaults required to false while the surrounding helpers default to true, producing mismatched nullability in generated model code. templates/unity/Assets/Runtime/Core/Client.cs.twig (chunked upload and cookie logging), templates/unity/Assets/Runtime/Realtime.cs.twig (null guard on connected data), and src/SDK/Language/DotNet.php (inconsistent required default in getPropertyAssignment). Important Files Changed
Reviews (4): Last reviewed commit: "Merge remote-tracking branch 'origin/mas..." | Re-trigger Greptile |
| buffer = ((byte[])input.Data) | ||
| .Skip((int)offset) | ||
| .Take((int)Math.Min(size - offset, ChunkSize - 1)) | ||
| .ToArray(); |
There was a problem hiding this comment.
Off-by-one in chunked upload byte-array path
.Take((int)Math.Min(size - offset, ChunkSize - 1)) takes one byte fewer than the Content-Range header advertises. The header at line 669 uses offset + ChunkSize - 1 as the inclusive end, meaning the server expects exactly ChunkSize bytes, but only ChunkSize - 1 are sent. For every chunk except the last, the uploaded content will be 1 byte short, causing the server to reject or silently misalign the upload. The stream and path cases read the full ChunkSize via ReadAsync, so only the bytes source type is affected.
| Debug.Log($"[Client] Setting cookie header: {cookieHeader}"); | ||
| request.SetRequestHeader("Cookie", cookieHeader); | ||
| } |
There was a problem hiding this comment.
Session cookie values written to Unity log in plain text
cookieHeader contains the full Cookie header value, which includes session tokens and other authentication credentials. Passing it to Debug.Log writes it in plain text to Unity's console output and any log file on disk. Anyone with access to the device's log files (or Unity console captures) can extract and replay the session. This block runs on all non-WebGL platforms (desktop, mobile, editor).
| case "stream": | ||
| var stream = input.Data as Stream; | ||
| if (stream == null) | ||
| throw new InvalidOperationException("Stream data is null"); | ||
| stream.Seek(offset, SeekOrigin.Begin); | ||
| await stream.ReadAsync(buffer, 0, ChunkSize); | ||
| break; |
There was a problem hiding this comment.
ReadAsync partial-read not handled for the last chunk
stream.ReadAsync(buffer, 0, ChunkSize) is not guaranteed to fill the entire buffer — it may return fewer than ChunkSize bytes, especially on the last chunk. The buffer is sized to ChunkSize at allocation time, so unread tail bytes retain the values from the previous iteration (or zeros on the first pass). Combined with the Content-Range header that declares the full chunk range, this means the final chunk can contain stale/zero-padded bytes, corrupting the uploaded file. The bytes path already handles this correctly with Take(…), so the stream path needs the same treatment.
| public function testHTTPSuccess(): void | ||
| { | ||
| // Set Unity test mode to exclude problematic files | ||
| $GLOBALS['UNITY_TEST_MODE'] = true; | ||
|
|
||
| parent::testHTTPSuccess(); | ||
| } |
There was a problem hiding this comment.
$GLOBALS['UNITY_TEST_MODE'] is never reset, leaking across tests
$GLOBALS['UNITY_TEST_MODE'] is set to true at the start of testHTTPSuccess but is never cleared afterwards. PHP globals persist for the entire test-runner process lifetime, so any subsequent call to Unity::getFiles() — from another test method in the same class or from a follow-up run in the same process — will silently apply the file-exclusion filter even when that wasn't intended. A tearDown that unsets the key, or better yet, an injectable flag rather than a global, would prevent this leakage.
|
|
||
| env: |
There was a problem hiding this comment.
UNITY_LICENSE exposed to every job in the workflow
Declaring UNITY_LICENSE in the top-level env: block makes it available to all jobs, including those that have nothing to do with Unity (Rust, Swift, Web, etc.). Keeping sensitive secrets scoped to the single matrix step or job that actually needs them is a standard least-privilege practice. Consider moving the env entry to the specific step that runs the Unity test command, or gate it with if: matrix.sdk == 'Unity2021'.
…ntinued # Conflicts: # .github/workflows/sdk-build-validation.yml
Summary
This PR continues the work started by @Fellmonkey in #1105 to add comprehensive Unity SDK support to the SDK generator.
What was done
unity-client-sdkbranch from Unity client sdk #1105unity-client-sdk-continuedpreserving all original commits from the community PRmasterand resolved conflicts (notably intemplates/dotnet/Package/Models/Model.cs.twig)Original PR content (from #1105)
Unitylanguage class (src/SDK/Language/Unity.php) that extends the baseLanguageclass, providing Unity-specific type mappings, keywords, and code generation logic for C# in Unity environment.templates/unity/Assets/including:Unity2021Test.phptest class that integrates with the existing test frameworkTests.cs,Tests.asmdef) for comprehensive SDK testingunityci/editor:ubuntu-2021.3.45f1-base-3.1.0UNITY_LICENSEenvironment variable for Unity Editor automationAssets/Runtime/andAssets/Editor/Changes from original PR
masterCloses #1105