feat: Add support for reflectapi(required) which will force an input to be required in the generated clients, even if it is optional/has a default. This allows for introduction of new required properties without breaking existing deployed clients.#121
Conversation
…t to be required in the generated clients, even if it is optional/has a default. This allows for introduction of new required properties without breaking existing deployed clients.
|
I don't really understand this. What's wrong with not specifying a default? |
There was a problem hiding this comment.
LGTM — clean, well-tested addition following existing patterns.
Extended reasoning...
Overview
This PR adds a #[reflectapi(required)] field attribute to the derive macro. Changes touch three small files in reflectapi-derive (new REQUIRED symbol, parsing support, and one-line logic change in derive.rs) plus a new test with five snapshot files covering the schema, TypeScript, Rust, OpenAPI, and Python outputs.
Security risks
None. This is a compile-time proc-macro attribute with no runtime security surface.
Level of scrutiny
Low. The implementation is a minimal, additive change — one new boolean field in ParsedFieldAttributes, one new symbol constant, one else if branch in the parser, and a single || added to the requiredness logic for inputs. The change is isolated to input field handling and does not affect output behavior.
Other factors
The snapshots fully validate the end-to-end behavior across all code-generation targets. The logic attrs.required || field.attrs.default().is_none() correctly preserves existing behavior (fields without a serde default are still required) while allowing opt-in forcing of requiredness. No bugs were found by the automated system, and there are no outstanding reviewer comments.
|
So I want to add a new field onto a request, but there are existing clients out in the world. To be used for adding a new field to a request, sort of like Postgres NOT VALID constraint. Best for endpoints with out of band consumers, e.g. Would also be useful for users who haven't refreshed their browsers in a while. |
|
I understand the use case now, thanks. It feels a little strange, I'll sit on it a bit. The patch is quite simple though which is good. I'm almost leaning towards something like |
|
I agree with Andy here. |
|
As in you're fine with |
|
I agree with you that the change almost like not very strongly justified (use case is quite weak, imo). |
For the quality ranks, how can we add a new required field to an existing API, while meeting this criteria:
For level 3/4 without this? The only method I see is creating an entirely new API version, which takes months for consumers to migrate. With the help of the type system we could add a new required field without breaking existing deployed clients, but still force build errors in the monorepo via the type system - encouraging rapid adoption. I am not familiar with |
|
The only path being a new version might be intentional, but I think it's a very high effort option for sometimes very small additions which we could accommodate in a backwards compatible fashion. |
|
Jo, use the transformers. It will help you to achieve exactly what you need. I am happy to see our reflectapi-ex crate helper In regards to the justification for the usecase. No need to convince me :) I got it you need it, and so reflectapi with help of transformers let's you do so cleanly. In regards to forward and backward compatibility. It would be typically achieved via these steps: |
No description provided.