Skip to content

Type asset_expression in the REST API so the UI does not cast through unknown#67725

Open
Anuragp22 wants to merge 2 commits into
apache:mainfrom
Anuragp22:type-asset-expression-api
Open

Type asset_expression in the REST API so the UI does not cast through unknown#67725
Anuragp22 wants to merge 2 commits into
apache:mainfrom
Anuragp22:type-asset-expression-api

Conversation

@Anuragp22
Copy link
Copy Markdown
Contributor

closes: #67692

asset_expression was declared as dict | None on the REST API response models, so the OpenAPI generator emitted { [k: string]: unknown }. The UI compensated by hand-maintaining an ExpressionType discriminated union in src/components/AssetExpression/ and casting the API value through it with no runtime check, so a change to the server shape would not be caught by the TypeScript build. This types the expression on the API side and lets the generated client describe it.

What changed:

  • Added a structured AssetExpression model in datamodels/common.py: a recursive discriminated union over the five shapes BaseAsset.as_expression() produces (asset, alias, asset_ref, any, all), following the existing Annotated[Union[...], Discriminator] pattern in that module. Asset leaves carry the id that DagModelOperation.update_dag_asset_expression injects when the expression is persisted. id is optional so a row written before id-enrichment, or migrated from the pre-3.0 dataset format, still validates instead of returning a 500.
  • Used the model for every response that serves the field: DAGDetailsResponse, DAGWithLatestDagRunsResponse, and both fields on the partitioned dag run responses.
  • Typed the next_run_assets UI endpoint with a new NextRunAssetsResponse model in datamodels/ui/assets.py instead of a bare dict. response_model_exclude_unset=True keeps the response shape identical to before.
  • Regenerated the OpenAPI spec and the TypeScript client.
  • Removed the hand-maintained ExpressionType union and the casts in AssetProgressCell.tsx and AssetSchedule.tsx; the UI now consumes the generated type. The more precise types also let some now-dead defensive code in AssetExpression.tsx be removed.

For expressions produced by the current code the emitted JSON is unchanged, so this is not a breaking change for API consumers; only the declared schema becomes precise.

Tests: added test_common.py covering round-trip serialization of every variant, the optional id behaviour, and rejection of malformed shapes. The existing next_run_assets and dag-detail route tests pass unchanged.


Was generative AI tooling used to co-author this PR?
  • Yes (please specify the tool below)

Generated-by: Claude Code (Claude Opus 4.8), reviewed and verified by the author

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

Labels

area:airflow-ctl area:API Airflow's REST/HTTP API area:UI Related to UI/UX. For Frontend Developers. backport-to-airflow-ctl/v0-1-test

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Type asset_expression on the API side so the UI doesn't cast through unknown

1 participant