-
-
Notifications
You must be signed in to change notification settings - Fork 114
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
Convert date strings to dates at runtime #670
Conversation
Run & review this pull request in StackBlitz Codeflow. |
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
Marking this ready for review since I'd like to get feedback on the general direction before completing the TODOs I've written up |
Hey @Nick-Luca I will have a look but currently busy with other projects for a few weeks |
Thanks! I think so long as I have an idea what your views are on the direction, I can finish it off and dogfood a fork for a while. We have a pretty complex API in my org so plenty of corner cases to discover I'm sure |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving a few clarifying comments to start off
dbf2107
to
2e9286f
Compare
Okay @mrlubos this is ready I believe. I've updated the RFC in the PR body and also documented the proposed limitations for the first version of this. I've linked it locally to my team's codebase. We have a 13,500 line OpenAPI spec from SpringDoc and it helped me fix one mistake but the rest looks good. I haven't got my own codebase compiling yet but that's because our BFF+UI are now on fire because a bunch of strings are now dates :D |
This is amazing @Nick-Lucas, I will review it + write docs |
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular_transform/types.gen.ts.snap
Show resolved
Hide resolved
strings?: Array<(string)>; | ||
}; | ||
|
||
export function ParentModelWithDates(data: any): ParentModelWithDates { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to add proper types here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's not much point, it's an internal function called by a part of the code that doesn't know the type because it's a response body, so you wouldn't get any compiler benefits. The mutations also benefit from any
because we don't have to do any casting during the transform, though that might not be an issue
I'm treating these similar to validation/parser logic in my mind. For instance Zod.parse is always unknown->MyType
albeit I'll cede that it checks every key in that situation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking it could help with catching incorrect transforms in tests... why not use unknown
over any
btw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You could be right, there's no harm in declaring the type on the input and I can't think of a reason it should cause compile issues unless there's a real issue in the transform. I was mostly just going after the validator/parser pattern that tools like Zod use, but it is slightly different here
There is a good reason to use any
over unknown
though, which is unknown means you can't chain up properties without do a "x" in y
check or using a type assertion first so the codegen would be way more verbose and difficult to generate. Any is like disabling typescript
I'm happy to switch things around to take the expected type as input. The main impact would be on the request files but I suspect since their type definition is unknown -> unknown
that will all work fine
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OH actually, I remember why I did it this way - static typed input would be nice, but I didn't want any risk of an unexpected response causing a property x of undefined
type error, and so every single access chain uses the optional chaining operator. If we gave it a static input type then is there a chance prettier/eslint could strip the "unnecessary optional chaining" since the input type is known and properties in each chain aren't technically optional?
packages/openapi-ts/test/__snapshots__/test/generated/v3_angular_transform/types.gen.ts.snap
Show resolved
Hide resolved
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #670 +/- ##
==========================================
- Coverage 75.67% 71.65% -4.03%
==========================================
Files 74 76 +2
Lines 7400 7895 +495
Branches 692 696 +4
==========================================
+ Hits 5600 5657 +57
- Misses 1797 2235 +438
Partials 3 3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
@Nick-Lucas since this changes types from string to Date, aren't you going to have an issue where requests now expect Dates according to TypeScript, but since there's no request transformer, we want to send strings? |
Yes because that's how the types emission currently works. Every JS request lib I know will serialise the dates into ISO strings, so I'm not expecting an issue really, unless someone has a format:date-time but is using a custom string format they want to manually serialise to. I was wondering if we need to flip around generation so that request/response types are generated and pull from the schemas (ie. request could be |
Do you want to merge and release this as is? Seems e2e tests are failing btw |
Hm if tests are failing because of these changes I'll need to have a look on Monday, everything I ran was passing but I maybe didn't get to run everything locally. Looks like the errors here are angular and due to window.api being undefined |
#145 asks for a way to transform the underlying data of a response when Date is set on the type itself.
For some use cases this would be inapropriate since it could bloat bundle size, but for many this is desirable behaviour. Bundle size could also be optimised a bit, but generating raw code to convert types is about the most efficient you can get for runtime performance
This PR is a first crack at adding optional transforms to the project.
Proposal:
readonly responseTransformer?: (data: unknown) => unknown;
- this way we can apply a transform to the result inside the CancellablePromise wrapper, so long as we implement a few lines within each clienttypes: { dates: true }
withboolean | "types" | "types+transform"
and leavetrue
as justtypes
export const ModelName = (data: unknown) => ModelName
- typescript is really great in this area, a type and a variable can have the same name so long as they're exported from the same file, and typescript will use the correct one contextuallyProposed limitations for the first iteration:
Work to do:
The above proposal produces output like the below: