Skip to content

TypeScript client: streams manifest is empty, and /stream endpoints are emitted as ordinary queries #106

Description

@juicycleff

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions