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

feat: add option noDefaultsForOptionals #1051

Merged
merged 5 commits into from
Jun 7, 2024

Conversation

robmonie
Copy link
Contributor

@robmonie robmonie commented May 31, 2024

Adds a new option - noDefaultsForOptionals that allows for compatibility with Square/Block's Wire Protobuf implementation with respect to defaulting of optional fields.

Note: As per the documentation added to the readme, this option provides non-standard protobuf behaviour so it would be understandable if this isn't something you'd like in the library. I'm hoping with the appropriate warning in the docs that you'll consider this as as option.

@robmonie robmonie changed the title Add option noDefaultsForOptionals feat: add option noDefaultsForOptionals May 31, 2024
@robmonie robmonie marked this pull request as draft May 31, 2024 04:29
src/main.ts Outdated
@@ -1249,10 +1248,14 @@ function generateDecode(ctx: Context, fullName: string, messageDesc: DescriptorP
${messageProperty} = ${generateMapType ? "new Map()" : "{}"};
}`
: "";

const ifValueCheck = `${varName}.value !== undefined ${withAndMaybeCheckIsNotNull(options, `${varName}.value`)}`;
const maybeIfKeyCheck = `${options.noDefaultsForOptionals ? ` && ${varName}.key !== undefined ${withAndMaybeCheckIsNotNull(options, `${varName}.key`)}`: ''}`
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change to map exists solely to satisfy the types. Now that both key and value are potentially undefined, assignment against an undefined key isn't valid so a check against both value and key is required. Is there possibly a better way to think about this?

@robmonie robmonie marked this pull request as ready for review May 31, 2024 04:38
@@ -0,0 +1,82 @@
// Code generated by protoc-gen-ts_proto. DO NOT EDIT.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This and other related files in this folder we generated from the existing base.proto as part of performing a build for tests.

@stephenh
Copy link
Owner

stephenh commented Jun 5, 2024

Hi @robmonie ! Sorry about that extension-import thing; I just fixed this up on main, can you try rebasing the PR and see if that works? Thanks!

@stephenh
Copy link
Owner

stephenh commented Jun 5, 2024

I looked into this a bit more, and huh, I had not heard of Wire/didn't know about their "primitives are always boxed" behavior. That is certainly different! Although ngl I think I prefer it; protobuf's optional behavior has been such a bug bear over the years.

Normally I'd want to keep this out of ts-proto, but the change is so relatively tiny, to our codebase, that 🤷 I guess it seems fine to me.

@robmonie just curious, but does Square actually have public-facing APIs that use the Wire protocol/behavior, or have you just seen/used Wire's behavior, and prefer it, and so would like to use it on your own/non-Square projects? Just curious!

@robmonie
Copy link
Contributor Author

robmonie commented Jun 5, 2024

Thanks for looking at this @stephenh. I'm not sure whether there are any externally facing apis that use Wire, however pretty much all the internal Apis, Events etc are based on protos written in Kotlin which use Wire as an internal standard. This makes interfacing with unsupported languages difficult.

The biggest issue comes from the default proto behaviour of not encoding default values such as false or 0, so when the client is based on ts-proto and the service is based on Wire, null values are not defaulted and as a consequence are interpreted as null, essentially making interoperability impossible unless it's accounted for on the Kotlin side. Unfortunately we interface with many preexisting apis that can't or shouldn't be changed to account for us as a client.

I'll do a rebase shortly and if there are any improvements you think I can make, let me know.

@robmonie robmonie force-pushed the no-defaults-for-optionals branch 3 times, most recently from bfaf8db to 0e920f1 Compare June 5, 2024 11:18
@stephenh stephenh merged commit 41d1020 into stephenh:main Jun 7, 2024
6 checks passed
@stephenh
Copy link
Owner

stephenh commented Jun 7, 2024

Looks great @robmonie , thanks!

stephenh pushed a commit that referenced this pull request Jun 7, 2024
# [1.177.0](v1.176.3...v1.177.0) (2024-06-07)

### Features

* add option `noDefaultsForOptionals` ([#1051](#1051)) ([41d1020](41d1020))
@stephenh
Copy link
Owner

stephenh commented Jun 7, 2024

🎉 This PR is included in version 1.177.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

timostamm added a commit to timostamm/ts-proto that referenced this pull request Jun 7, 2024
The PR added new tests, and we need to re-generate the proto files.
@robmonie
Copy link
Contributor Author

robmonie commented Jun 8, 2024

Looks great @robmonie , thanks!

Thanks @stephenh. Much appreciated :-)

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

Successfully merging this pull request may close these issues.

None yet

2 participants