Skip to content

refactor(ui): migrate API client codegen from hey-api to orval - #7023

Open
luizhf42 wants to merge 5 commits into
masterfrom
feat/ui/orval
Open

refactor(ui): migrate API client codegen from hey-api to orval#7023
luizhf42 wants to merge 5 commits into
masterfrom
feat/ui/orval

Conversation

@luizhf42

@luizhf42 luizhf42 commented Sep 2, 2026

Copy link
Copy Markdown
Member

Migrates the console's OpenAPI client codegen from @hey-api/openapi-ts to Orval. Tracked in shellhub-io/team#236.

What

Replaces the entire hey-api codegen pipeline — generated SDK, interceptor chain, thin query/mutation wrapper hooks, manual cache invalidation — with Orval's generated hooks and declarative config. 246 files changed, net −4454 lines.

Changes

  • Orval codegenorval.config.ts replaces openapi-ts.config.ts; generate-client.sh calls orval instead of openapi-ts; output is src/client/api.ts + src/client/model/
  • customInstance.ts — single custom mutator replaces the three-file interceptor chain (fetchClient.ts, fetchInterceptors.ts, fetchInterceptors.test.ts). Handles auth/JWT expiry, 401/MFA, connectivity monitoring, X-Total-Count attachment on array responses, and error enrichment. Exports fetchWithHeaders for the two auth flows that read response headers (x-mfa-token, x-expires-at)
  • totalCount() accessor — reads the non-enumerable totalCount property attached by customInstance, replacing paginatedQueryFn and fetchWithHeaders for paginated lists
  • Declarative mutationInvalidates — 25 invalidation groups in orval.config.ts replace 15 hand-written mutation hook files. Detail-page invalidation is handled in custom hooks where the entity ID is available (Orval's matchQuery does element-wise key comparison, not prefix matching)
  • ~30 thin wrapper hooks deleted — query hooks that just forwarded to the SDK and mutation hooks that only wired useInvalidateByIds. Consumers call Orval-generated hooks directly (useGetDevices, useGetSessionsAdmin, useClsoeSession, etc.)
  • ~9 domain hooks rewritten — multi-step mutation hooks (useAddDeviceTag, useAddContainerTag, useDeviceActionRunner, useContainerActionRunner, useAcceptDeviceByCode, useSSHApproval, useNamespaceMutations) updated to Orval's flat variable shape ({ uid, data } instead of { path: { uid }, body })
  • useTagNames() — centralizes the useGetTags({ page: 1, per_page: 100 }) + .map(t => t.name) pattern used by 4 tag-related components
  • Settings pageuseDeleteNamespace and useLeaveNamespace inlined with a shared logoutAndRedirect() helper
  • Filter inliningbuildNameFilter, buildUsernameFilter, etc. moved from deleted hooks into their single consumer pages
  • useNamespaces.ts trimmeduseInitRole inlined into NamespaceGuard, useNamespaceMembers inlined into MembersTab
  • useLatestAnnouncement inlined — chained queries now live in AnnouncementModalTrigger
  • signUpStore.ts fixedregisterUser response was being discarded; now reads the UserAuth return properly (depends on fix(server): return 204 from registerUser when no auth is issued #7042 for the correct 200/204 split)
  • Admin cargo-cult options removedstaleTime, retry (dead code since customInstance redirects on 401), refetchOnWindowFocus: false, enabled: isAdmin (redundant behind AdminRoute)
  • MSW test migrationmockSdkGen was replaced by MSW handlers, intercepting the endpoints instead of mocking the SDK, validating Orval functionality with the customInstance.

@otavio

otavio commented Sep 9, 2026

Copy link
Copy Markdown
Member

/review

1 similar comment
@otavio

otavio commented Sep 9, 2026

Copy link
Copy Markdown
Member

/review

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Code Review Complete

The automated review ran but did not post an updated summary — this usually means no new issues were found since the previous review. If you've pushed changes and want a fresh pass, comment /review.

View job

Orval replaces `@hey-api/openapi-ts` as the OpenAPI client generator.
The config enables react-query hooks, and MSW/faker mock generation from the spec.
The custom mutator merges `fetchClient` and `fetchInterceptors` into
a single function that handles auth, JWT expiry, 401/MFA, connectivity
tracking, and error enrichment. `fetchWithResponse` is exported alongside
for paginated hooks that need access to response headers.
The hey-api SDK barrel (`@/client`) is replaced by orval's generated
`@/client/api` and `@/client/model` imports. Thin single-consumer
wrappers are deleted and inlined into their call sites in the next
commits. Paginated hooks now use orval-generated hooks directly —
`customInstance` attaches `X-Total-Count` as a non-enumerable property
on array responses, and a `totalCount()` accessor reads it.
The old `mockSdkGen` / `vi.doMock("@/client/sdk.gen")` approach mocked
at the SDK function layer. MSW intercepts at the HTTP boundary, so tests
now exercise the real React Query hooks, `customInstance`, and Orval
fetch functions with only the HTTP responses faked.

Infrastructure: add `msw.ts` (shared server + `jsonWithTotal`, `setTags`,
`parseBody` helpers), export `VALID_JWT` from `seedAuthStore` (the
factory token now passes `isTokenExpired`), tighten
`onUnhandledRequest` to `"error"`, and delete the old `sdk.ts`,
`globals.d.ts`, `mockNamespaces.ts`, `mockTags.ts` helpers.
@luizhf42
luizhf42 added this pull request to stack #7066 September 9, 2026 21:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants