We generate four clients from one gateway (identity, portal, studio, twinos) on @forge-go/client-core 1.10.4. All four come out with an empty streams table:
// packages/client/forge/twinos/stream-bindings.ts
export const streams = [] as const;
Same for the other three.
That leaves the stream runtime with nothing to run on, because StreamBinder is driven entirely by that manifest. You can build the binder and a SubscriptionManager, and cache.live gets assigned, but no query can ever be live: the channel lookup resolves to empty for every one of them, so no socket is opened and the devtools panel reports an attached binder with zero channels.
We wired it up anyway. It costs one object and no network, and nothing on our side has to change when bindings do start showing up.
So the question is what gets rows into that table. Two parts of it we cannot work out from the client side.
The first is what a service has to declare. The generator clearly ran, since it wrote the file with an empty array instead of skipping it, which means it looked and found nothing to write. Is there a registration on the Go side we've missed, or does the streaming extension need wiring into the pass that builds the IR? Our backend serves WebSocket and SSE endpoints today. They are just not reaching the manifest.
The second is what becomes of endpoints that already look like streams. Anything whose path ends in /stream comes out as an ordinary query binding:
export const op_streamAdminInstanceLogs = {
method: 'GET',
path: '/portal/api/portal/admin/instances/{instanceId}/logs/stream',
provides: [],
invalidates: [],
} as const satisfies OperationMeta;
export const useStreamAdminInstanceLogs = query(op_streamAdminInstanceLogs);
There are six in portal, covering instance and workload health, logs and usage. Calling one through useQuery issues a plain fetch at a streaming endpoint, so it either hangs or swallows the whole stream as a response body. Nothing in our app calls them, so it's a trap and not a live bug. The name is inviting though, and query(...) gives no hint that it is not one.
Can the IR carry that a response streams, so the generator emits something else for it, or leaves it out of the client?
Happy to test a fix against our gateway. It fronts four services and a wide spread of endpoints, so it tends to turn this kind of thing up early.
We generate four clients from one gateway (identity, portal, studio, twinos) on
@forge-go/client-core1.10.4. All four come out with an empty streams table:Same for the other three.
That leaves the stream runtime with nothing to run on, because
StreamBinderis driven entirely by that manifest. You can build the binder and aSubscriptionManager, andcache.livegets assigned, but no query can ever be live: the channel lookup resolves to empty for every one of them, so no socket is opened and the devtools panel reports an attached binder with zero channels.We wired it up anyway. It costs one object and no network, and nothing on our side has to change when bindings do start showing up.
So the question is what gets rows into that table. Two parts of it we cannot work out from the client side.
The first is what a service has to declare. The generator clearly ran, since it wrote the file with an empty array instead of skipping it, which means it looked and found nothing to write. Is there a registration on the Go side we've missed, or does the streaming extension need wiring into the pass that builds the IR? Our backend serves WebSocket and SSE endpoints today. They are just not reaching the manifest.
The second is what becomes of endpoints that already look like streams. Anything whose path ends in
/streamcomes out as an ordinary query binding:There are six in portal, covering instance and workload health, logs and usage. Calling one through
useQueryissues a plain fetch at a streaming endpoint, so it either hangs or swallows the whole stream as a response body. Nothing in our app calls them, so it's a trap and not a live bug. The name is inviting though, andquery(...)gives no hint that it is not one.Can the IR carry that a response streams, so the generator emits something else for it, or leaves it out of the client?
Happy to test a fix against our gateway. It fronts four services and a wide spread of endpoints, so it tends to turn this kind of thing up early.