Skip to content
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

Support phase-specific renames #190

Open
willcrichton opened this issue Dec 18, 2023 · 5 comments
Open

Support phase-specific renames #190

willcrichton opened this issue Dec 18, 2023 · 5 comments
Labels
breaking change This will probs end up in the next major version.

Comments

@willcrichton
Copy link

I have a type like this:

#[derive(Serialize, Deserialize, specta::Type)]
pub struct Package {
  #[serde(rename(deserialize = "@version"))]
  pub version: String,
}

But specta (2.0.0-rc7) raises the error:

error: specta: expected string literal. Eg. `"somestring"`
  --> crates/bene-epub/src/lib.rs:16:11
   |
16 |   #[serde(rename(deserialize = "@version"))]
   |           ^^^^^^
@oscartbeaumont
Copy link
Owner

oscartbeaumont commented Dec 19, 2023

Hmm, how would you expect this to act?

It's a challenge because we export a single named type (export type Package) so we would need to unify the serialize and deserialize types, probably like the following:

export type Package = {
    version: string,
} | {
    "@version": string
};

Is something preventing you from just using a normal rename?

@willcrichton
Copy link
Author

willcrichton commented Dec 19, 2023

I see your point. My use-case is that I am deserializing an XML file in Rust (using quick_xml's naming conventions), and then serializing this type into JSON to pass to Typescript. In my particular use-case, I never need to serialize the type within Typescript, so it would be fine for the Typescript field name to only take the serialize name and not the deserialize. I am trying to avoid having to duplicate the Package type definition.

One possibility is that I could tell specta to ignore/override the serde attribute, like this:

#[derive(Serialize, Deserialize, specta::Type)]
pub struct Package {
  #[serde(rename(deserialize = "@version"))]
  #[specta(rename = "version")]
  pub version: String,
}

@oscartbeaumont
Copy link
Owner

Thinking about it,

I would be fine adding the per-phase metadata for rename and anything other property that isn't symmetrical. This data would be especially useful in something like rspc which could actually use that information safely given its full control over the transport layer.

For the "less sophisticated" exporters like specta::export I don't exactly know what would be the best way to use this information as we can't guarantee the types will be used for the correct phase. I suspect we would default to the enum of both phases to be conservative.

We could probably allow a complete export for each phase similar to the bigint configuration and leave it up to the user to ensure they are used correctly.

Are you using specta::export, the lower level specta::ts::* api's or another exporter like rspc, tauri-specta, etc?

@willcrichton
Copy link
Author

I am using tauri-specta. This is the return type from a Tauri command.

@Brendonovich
Copy link
Collaborator

I'm not sure what other attributes would need phase-specific support, but i think this could go nicely with #76, where we use the union type by default but remove options from it if they're never going to be hit.

@oscartbeaumont oscartbeaumont added the breaking change This will probs end up in the next major version. label Jan 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
breaking change This will probs end up in the next major version.
Projects
None yet
Development

No branches or pull requests

3 participants