Skip to content

Defer UI codegen upgrade: @7nohe/openapi-react-query-codegen v1→v2 (+ ts-morph 28) needs a full data-layer rewrite #71436

Description

@pierrejeambrun

Background

The grouped edge-UI dependency bump in #70777 split out one item as follow-up work:

@7nohe/openapi-react-query-codegen 1 → 2 (+ ts-morph 28)

This issue documents why that upgrade is deferred and captures the measured cost, so it isn't re-attempted as a routine version bump.

Why v2 is a breaking change (not a bump)

@7nohe/openapi-react-query-codegen v2 delegates generation to @hey-api/openapi-ts and emits a fundamentally different client:

  • Call arguments are restructured: flat camelCase → nested snake_case { path, query, body }.
    // v1
    mutate({ dagId, requestBody: {} })
    useX({ limit, orderBy })
    // v2
    mutate({ path: { dag_id: dagId }, body: {} })
    useX({ query: { limit, order_by } })
  • Function SDK instead of service classes (AssetService.getAssets(...)getAssets(...)).
  • Result shape becomes { data, error }; body replaces requestBody.
  • Mutation option placement (onSuccess/onError) changes.
  • The hand-rolled ApiError / OpenAPI runtime is replaced by the @hey-api/client-* runtime.

Measured migration cost

Prototyped locally: regenerated openapi-gen/ with v2 + @hey-api/client-axios, then applied the mechanical symbol renames (hooks lose the Service infix, response types are re-cased, e.g. useAssetServiceGetAssetsuseGetAssets, DAGRunResponseDagRunResponse) — ~684 identifiers, verified against the generated exports.

After the renames, ~827 tsc errors remain across ~216 files, now dominated by call-site argument restructuring:

  • TS2353 (unknown property in Options<…>): ~249
  • TS2345 (argument type): ~117
  • TS2322 (type mismatch): ~269

There are ~513 flat-argument call-site lines (48 files use requestBody). This part is not scriptable — each operation's path/query/body split and key-casing differ, and path params are typed unknown, so a wrong split is a runtime bug tsc won't catch. It is also all-or-nothing: the UI does not compile until every call site is migrated, so it cannot land incrementally.

ts-morph 28 is coupled to v2

ts-morph is used only by the code generator (no direct imports in airflow-core/src/airflow/ui/src). v1 declares ts-morph 22.x as a peer and already runs on 27; it also runs cleanly on 28 (verified: deterministic output, tsc 0 errors, no consumer changes — only generated optional types gain an explicit | undefined/| null). But bumping ts-morph to 28 on v1 delivers no functional benefit — 28 is required only by v2. The two should therefore move together.

Work required to complete (acceptance criteria)

  • Regenerate openapi-gen/ with @7nohe v2 + a @hey-api/client-* runtime; update the codegen script.
  • Re-wire client config: base URL via client.setConfig({ baseURL }), path-param encoding, and the request/response interceptors onto client.instance (preserving the current 401/403 redirect + 403-URL-blocking behavior). The hand-rolled fetch/axios callers (useGridTiSummaries, useHITLReviewTabs) must keep working via client.getConfig().baseURL.
  • Migrate all ~513 call sites to structured snake_case { path, query, body } args, .data result handling, new mutation-option placement, and the v2 error type.
  • Bump ts-morph to 28 as part of the same change.
  • Green tsc, ESLint, Vitest, vite build, and a Playwright smoke pass.

Notes for whoever picks this up

The client re-wire and the mechanical symbol-rename map are straightforward and were prototyped; the bulk of the effort is the per-call-site argument restructuring, which needs manual attention and review site by site.

Related: #70777

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:UIRelated to UI/UX. For Frontend Developers.kind:featureFeature Requests

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions