Fix passthrough additionalProperties fallback for models with typed properties#1560
Fix passthrough additionalProperties fallback for models with typed properties#1560lohanidamodar wants to merge 3 commits into
Conversation
Greptile SummaryThis PR delivers two coordinated fixes: it restores the unconditional whole-map fallback in
Confidence Score: 5/5Safe to merge; all changed paths have been cross-checked and the whole-map fallback is correctly restored for every affected language. The regression fix is straightforward and consistent across all four affected templates. The vendor-extension removal is mechanical — every template that read No files require special attention. Important Files Changed
Reviews (5): Last reviewed commit: "Fix Swift Model template passthrough fal..." | Re-trigger Greptile |
…roperties Commit 171408b ("refactor: remove expiry handling and improve additional properties handling in models", PR #1543) added a property-count branch in the Dart, Kotlin and Android model templates that picked the wrong fallback when a model defines BOTH typed properties AND additionalProperties: true. For affected models (Row, Document, Presence) the generated fromMap used an empty-map fallback (Map<String, dynamic>.from(map["data"] ?? {}) in Dart, emptyMap<String, Any>().jsonCast(to = nestedType) in Kotlin/Android) instead of falling back to the whole input map. This silently dropped user-defined columns/fields when the server response omitted the additionalProperties key. Collapse the inner property-count branch so the whole-map fallback (?? map / ?: map.jsonCast(to = nestedType)) is always emitted whenever additionalProperties is true. The additionalPropertiesKey extension (used by e.g. Presence's "metadata") is preserved. Co-Authored-By: Damodar Lohani <dlohani48@gmail.com>
Removes the vendor-extension-driven indirection that allowed Appwrite
response models to redirect a passthrough additionalProperties payload
into a custom-named field (e.g. metadata) in generated SDKs. With the
upstream Appwrite spec dropping the x-additional-properties-key emission
in favour of expressing such fields as ordinary typed properties of
type object with additionalProperties: true, the sdk-generator side of
the mechanism is dead code and a non-standard barrier for any downstream
adopter generating SDKs from a vanilla OpenAPI 3 spec.
- src/Spec/Swagger2.php: stop reading x-additional-properties-key.
- templates/{dart,kotlin,android,swift,php,dotnet,ruby,rust,python}:
replace definition.additionalPropertiesKey lookups with the literal
'data' field name (the previous default).
6e28857 to
ae438ad
Compare
df6ba23 to
ae438ad
Compare
The Swift template still carried the property-count branch that the dart, kotlin, and android templates lost in the parent commit: mixed models (typed properties + additionalProperties: true) fell through to JSONSerialization of an empty [:] dict when map["data"] was absent. For Row and Document — whose user data lives inline at the top level of the response, not nested under a "data" key — this silently discarded the entire payload, matching the regression we fixed in the other three languages. Collapse to the whole-map fallback (?? map) the else branch already used for pure-passthrough models. Generated examples/swift/Sources/ AppwriteModels/Row.swift now emits map["data"] ?? map alongside the other SDKs. Catch by greptile-apps[bot] inline review.
What changed
Two related fixes for the model passthrough/additionalProperties handling. Sister PR on the Appwrite side that emits the spec: appwrite/appwrite#12403.
1. Fix the regression in
fromMapfallback (commit 1)Commit 171408b (PR #1543) added a
definition.properties | length > 0branch around the??fallback in the dart/kotlin/android Model templates. Models that have BOTH typed properties AND outeradditionalProperties: true(Document, Row, Presence, etc.) ended up emitting an empty-map fallback (?? {}/?: emptyMap()), which silently drops user payloads when the response is inline (e.g. Row's user columns live at the top level next to$id, not nested under adatakey).This restores the unconditional whole-map fallback so the same code path that worked before #1543 keeps working. Swift template is unaffected — it uses Codable and never had the branch.
2. Drop the
x-additional-properties-keyvendor extension (commit 2)The extension let an Appwrite response model declare a custom name (e.g.
metadata) for the passthrough field in the generated SDK, on top of marking the outer schema asadditionalProperties: true. This conflated two distinct OpenAPI 3 concepts:additionalProperties: true— extras are inline siblings of typed properties. Standard.objectwithadditionalProperties: trueon that property. Standard.The vendor extension was being used to model the second case via the first one, which required generator-side special handling and made sdk-generator non-portable for anyone consuming a vanilla OpenAPI 3 spec.
This PR removes:
x-additional-properties-keyreading fromsrc/Spec/Swagger2.php,definition.additionalPropertiesKey | default('data')lookup from every template that used it (dart, kotlin, android, swift, php, dotnet, ruby, rust, python — model and test templates).All templates now emit the literal
'data'field name for inline-passthrough models — same default as before. The sister Appwrite PR (#12403) migrates the one consumer (Presence) to a normal typedmetadataproperty and removes the emission side of the extension.Why now
After #12403 lands, no Appwrite spec will emit
x-additional-properties-keyanymore. The reading was already dead in CI:mock-server/(the spec source for sdk-generator's integration tests) has no models that use the extension.Verification
composer lint-twig: 539 files, 0 errors.?? map(whole-map fallback) infromMapagain.