Skip to content

Decouple ui/* from api/* via openapi types #4725

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 29 commits into
base: fe/feature/RI-7039-replace-eui
Choose a base branch
from

Conversation

KrumTy
Copy link
Collaborator

@KrumTy KrumTy commented Jul 16, 2025

Issue

Currently we have a lot of typescript issues on the client side. Many of them are due to references to the nestjs api and/or mismatch between api contracts.

What this PR does

It addresses decoupling the ui/* from api/* be leveraging auto generated types based on openapi (swagger).
It shrinks the tsc errors by about 50% (from ~2500 to ~1300) and sets the path for further ts fixes.

Review guide

This PR appears large at first but that's because of the large amount of autogenerated types. Do not review the ui/src/api-client folder

Notes

  • When an api controller changes (param/dtos/etc), generate-client script needs to be rerun in order to generate the new types for the client. Not sure if this can be automated.
  • There's an option to split the autogenerated types into multiple files (one per type) but searching through the codebase with so many overlapping file names becomes too hard, so I kept them in one (api/clinet/api.ts)

@KrumTy KrumTy changed the title Feature/resolve ts issues Decouple ui/ from api/ via openapi types Jul 16, 2025
@KrumTy KrumTy changed the title Decouple ui/ from api/ via openapi types Decouple ui/* from api/* via openapi types Jul 16, 2025
Copy link
Contributor

github-actions bot commented Jul 16, 2025

Code Coverage - Integration Tests

Status Category Percentage Covered / Total
🟢 Statements 81.76% 16250/19874
🟡 Branches 64.83% 7333/11310
🟡 Functions 70.87% 2280/3217
🟢 Lines 81.4% 15283/18774

Copy link
Contributor

github-actions bot commented Jul 16, 2025

Code Coverage - Backend unit tests

St.
Category Percentage Covered / Total
🟢 Statements 92.36% 13788/14928
🟡 Branches 74% 4143/5599
🟢 Functions 85.96% 2124/2471
🟢 Lines 92.15% 13178/14300

Test suite run success

2940 tests passing in 286 suites.

Report generated by 🧪jest coverage report action from 5c05cfb

Copy link
Contributor

github-actions bot commented Jul 16, 2025

Code Coverage - Frontend unit tests

St.
Category Percentage Covered / Total
🟢 Statements 81.27% 18867/23214
🟡 Branches 66.93% 8214/12273
🟡 Functions 74.71% 4971/6654
🟢 Lines 81.67% 18468/22612

Test suite run success

4802 tests passing in 631 suites.

Report generated by 🧪jest coverage report action from 5c05cfb

@KrumTy KrumTy marked this pull request as ready for review July 16, 2025 14:56
@@ -172,7 +174,6 @@
],
"moduleNameMapper": {
"src/(.*)": "<rootDir>/$1",
"apiSrc/(.*)": "<rootDir>/$1",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this unused?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so

@valkirilov
Copy link
Collaborator

Great job on this, using an OpenAPI contract to keep services in sync is a solid and widely used approach, especially when different tech stacks are involved or when the code lives in separate repos. In those situations, generating types from Swagger docs makes it easier to keep services aligned and follow the correct communication protocol.

That said, in our case, we're working in a monorepo, and both the backend and frontend use TypeScript. I don't want to sound too negative, but adding a (semi-automatic) code generation tool here feels like extra complexity and might hide the real issue that we don't have a single source of truth for our types.

Instead of adding another layer, I think it would be more effective to focus on fixing the type mismatches directly. We could do this by adjusting how the frontend uses the types, or better yet, by introducing a shared types package (or something similar) so both sides rely on the same definitions.

Another thing to consider is that OpenAPI doesn't always match perfectly with the actual TypeScript code, so I think it's better to stick to the code interfaces as the main source of truth.

That said, if there are plans to move away from the monorepo and split the services, then generating types from Swagger would absolutely make sense, and it will probably be the best approach. I'm not against it overall, just think we should focus on solving the core issue first.

So, I'll be happy to chat more about this so we can agree on which is the best way to reduce these TypeScript errors and resolve the type mismatches between the BE and the FE.

@pd-redis
Copy link
Collaborator

Great job on this, using an OpenAPI contract to keep services in sync is a solid and widely used approach, especially when different tech stacks are involved or when the code lives in separate repos. In those situations, generating types from Swagger docs makes it easier to keep services aligned and follow the correct communication protocol.

That said, in our case, we're working in a monorepo, and both the backend and frontend use TypeScript. I don't want to sound too negative, but adding a (semi-automatic) code generation tool here feels like extra complexity and might hide the real issue that we don't have a single source of truth for our types.

Instead of adding another layer, I think it would be more effective to focus on fixing the type mismatches directly. We could do this by adjusting how the frontend uses the types, or better yet, by introducing a shared types package (or something similar) so both sides rely on the same definitions.

Another thing to consider is that OpenAPI doesn't always match perfectly with the actual TypeScript code, so I think it's better to stick to the code interfaces as the main source of truth.

That said, if there are plans to move away from the monorepo and split the services, then generating types from Swagger would absolutely make sense, and it will probably be the best approach. I'm not against it overall, just think we should focus on solving the core issue first.

So, I'll be happy to chat more about this so we can agree on which is the best way to reduce these TypeScript errors and resolve the type mismatches between the BE and the FE.

I don't think BE types should be used at all on FE, besides in the apiService.
Many type problems are caused because RedisString can be either string or RedisStringBuffer, and its being used as a string in most places, but in a few it is converted to string or to buffer. However, it is not actually a Buffer, but a data structure with type and data properties - so in this example, I don't think it should be typed as Buffer (it is send like one from BE, but serialized to JSON as plain object), but as:

{
type: string
data: number[]
}

Since we're passing via the API, using the same types is a lie for anything that is not supported by JSON and converting from json to buffer for example is a waste since we don't use it as buffer anywhere

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants