Answer with a list, not a bare array - #1409
Open
darksidemilk wants to merge 1 commit into
Open
Conversation
darksidemilk
added a commit
to darksidemilk/FogApi
that referenced
this pull request
Aug 27, 2026
Building the generated module for the first time turned up three things the generator cannot do. Two are handled here; the third is upstream in FOGProject/fogproject#1409. MULTIPART Snapin_CreateWithFile and Storagegroup_UploadSnapinFile are removed. AutoRest cannot generate compilable code for multipart/form-data at all, and this is not FOG's document being wrong: a minimal probe -- one object with a single `file` property, type string, format binary -- fails identically, 6 CS0411 errors on Extensions.AddIf<T> and Enumerable.Select. An array of files fails the same way. Reach these two through Invoke-FogApi, which exists for exactly this. TWO CMDLETS THAT WERE REALLY FOUR OPERATIONS Export-ProxyCmdlet refuses a cmdlet whose parameter has two types, and two pairs of unrelated operations were being merged into one cmdlet each: Join-FogGroup PUT /group/join applies one group's fields to a list of ids; POST /group/join resolves names and creates what is missing. -Body ended up with both bodies. New-FogTask `task` is one of Route::$validTaskingClasses, so POST /task/{id}/task exists beside POST /task. Their ids are Task_CreateTask and Task_Create, and AutoRest reads the verb off the front of the action and folds the repeated "Task", so both land on New-FogTask. -Body, -Shutdown and -Wol each ended up with two types. Naming the bodies upstream does not fix either one -- two named types are still two types on one parameter. They have to be separate cmdlets, so each POST is renamed to its own subject: Join-FogGroupByName and New-FogTaskQueue. Found by scanning the generated cmdlets for parameters declared with more than one type, rather than one twelve-minute build at a time. There were exactly three, all on New-FogTask, and none anywhere else in 474 cmdlets. surface.txt records the result, and shows the whole change in six lines -- which is what it is for, now that the generated tree is not committed. VERIFIED With #1409 applied to the document, the module builds and imports for the first time: 0 compile errors, FogApi.private.dll at 20.6 MB, 474 commands exported, every one Verb-Fog*, no collision with a built-in, and Get-Help returning FOG's own descriptions. Co-Authored-By: Claude <noreply@anthropic.com>
108 operations answered with a bare top-level JSON array. No code
generator can model that, and until now nobody had tried: generating
FOG's document has always reported success, but the C# it produces had
never been compiled. It does not compile. 333 errors, from a run with
zero warnings.
AutoRest builds no model for a top-level array, falls back to the only
named schema on the operation -- Error -- and then writes `.Count`,
`[0]` and `foreach` against it. Its own comment on the generated line:
// (await response) // should be FogApi.Models.IError
// response should be returning an array of some kind.
MEASURED BEFORE CHANGING A WIRE FORMAT
Naming the schema was tried first and does not work. Five response
shapes were generated and compiled:
inline array, items {type: object} fails
$ref to a NAMED top-level array schema fails
inline array whose items are a named object fails
inline array of integers fails
an object wrapping the array COMPILES
So this is not a naming problem and there is no document-only fix. The
rows have to sit under a property, which is where every list route
already puts them -- /list has always returned an envelope with `data`,
and these routes were the inconsistent ones.
WHAT CHANGED
/{class}/ids, /{class}/names 104 routes, now {"data": [...]}
/availablekernels, /availableinitrds now {"data": [...]}
Two more were not wire changes at all, but the document lying about its
own server:
/pendingmacs delegates to Route::listem(), so it has always answered
with a full page. Documented as a bare array. Now points at
MACAddressAssociationPage.
POST /{class}/join was documented as returning an array of ids. It
never has: Route::joining() ends at sendResponse($code) with no body,
so a generated client was told to wait for a list that never arrives.
Now documented as 201 with no content.
/system/export also loses `format: binary` -- AutoRest cannot model a
binary response and emits File.WriteAllBytes(path, result) with result
typed as the error schema. The content type is irrelevant:
application/sql, application/octet-stream and text/plain all compile
once the binary format is dropped, and a SQL dump is text, so a plain
string is the honest declaration.
CONSUMERS
One first-party caller reads a changed route:
fog.host.list.js drives the group typeahead on the host list from
/group/names and did `$.map(data, ...)` plus `data.length`. Updated, and
written to accept both shapes so the page keeps working against a server
that has not been updated yet.
RESULT
Generated, compiled and imported, which had never been done before:
compile errors 333 -> 0
FogApi.private.dll builds, 20.6 MB
module imports 474 commands, all Verb-Fog*, no collisions
Get-FogHostId/Name exist for the first time
Get-Help Get-FogHost returns FOG's own descriptions
Two multipart/form-data routes remain ungeneratable and are excluded
client-side. That one is not fixable here: a minimal probe -- one object
with a single `file` property -- fails identically, so AutoRest cannot
do multipart at all.
darksidemilk
force-pushed
the
openapi-named-array-responses
branch
from
August 27, 2026 01:46
35d44bd to
d601a9f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is the blocker. 108 operations answer with a bare top-level JSON array, and no code generator can model that — so no generated client of FOG's API compiles, in any language. Unlike #1408 (which is cosmetic), nothing downstream works until this lands.
Until now nobody had tried. Generating FOG's document has always reported success — but generating and compiling are different gates, and only the first was ever checked. The C# does not compile: 333 errors, from a run with zero warnings.
AutoRest builds no model for a top-level array, falls back to the only named schema on the operation (
Error), then writes.Count,[0]andforeachagainst it. Its own comment on the generated line:Measured before changing a wire format
Naming the schema was tried first, and does not work. Five response shapes were generated and compiled:
items: {type: object}$refto a named top-level array schemaSo there is no document-only fix. The rows have to sit under a property — which is where every list route already puts them.
/listhas always returned an envelope withdata; these routes were the inconsistent ones.What changed
/{class}/idsand/{class}/names— 104 routes, now{"data": [...]}/availablekernels,/availableinitrds— now{"data": [...]}Two more were not wire changes at all, but the document lying about its own server:
/pendingmacsdelegates toRoute::listem(), so it has always answered with a full page. It was documented as a bare array. Now points atMACAddressAssociationPage.POST /{class}/joinwas documented as returning an array of ids. It never has —Route::joining()ends atsendResponse($code)with no body, so a generated client was told to wait for a list that never arrives. Now documented as201with no content./system/exportalso losesformat: binary. AutoRest cannot model a binary response and emitsFile.WriteAllBytes(path, result)withresulttyped as the error schema. The content type is irrelevant —application/sql,application/octet-streamandtext/plainall compile oncebinaryis dropped, and a SQL dump is text, so a plain string is the honest declaration.Consumers
One first-party caller reads a changed route.
fog.host.list.jsdrives the group typeahead on the Host list page from/group/names, doing$.map(data, …)anddata.length. Updated — and written to accept both shapes, so the page keeps working against a server that has not been updated yet.Result
Generated, compiled and imported, which had never been done before:
FogApi.private.dllVerb-Fog*, no collisionsGet-FogHostId/Get-FogHostNameGet-Help Get-FogHostTwo
multipart/form-dataroutes remain ungeneratable and are excluded client-side. That one is not fixable here — a minimal probe (one object, onefileproperty) fails identically, so AutoRest cannot do multipart at all.Independent of #1408; both touch
openapi.class.phpand may need a trivial rebase depending on merge order.