Skip to content

Conversation

@tstirrat15
Copy link
Contributor

@tstirrat15 tstirrat15 commented May 23, 2025

Fixes #38

Description

protobuf-es is a more modern take on a TS-based implementation of protobuf and clients. I'm considering using it for authzed-node, but I wanted to test it out in the real world; this library seems like a good place to do that.

Notes

This adds about 100kb of bundle size, which isn't ideal, but we're also already at 5mb.

Changes

Will annotate

Testing

Review. See that tests pass and that playground functionality still works as expected.

@vercel
Copy link

vercel bot commented May 23, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 25, 2025 1:59pm

@tstirrat15
Copy link
Contributor Author

tstirrat15 commented May 23, 2025

There's something funky with check watches. Wasm isn't working in development, which would be necessary to debug it. I'll work on that later.

Copy link
Contributor Author

@tstirrat15 tstirrat15 left a comment

Choose a reason for hiding this comment

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

See comment

version: "v2"
plugins:
- remote: "buf.build/community/timostamm-protobuf-ts:v2.9.1"
- remote: "buf.build/bufbuild/es:v2.4.0"
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 swaps in the new codegen.

Comment on lines -8 to -11
import {
Struct,
Value,
} from "../spicedb-common/protodefs/google/protobuf/struct";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's lots of places where we were using Struct that we no longer need to, because protobuf-es automatically converts a normal JS object to Structs and Values where needed. This is one of the big ergonomic benefits.

Comment on lines +105 to +106
if (t.resolution.case === "subProblems") {
t.resolution.value.traces.forEach(appendExpanded);
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 is the difference in how protobuf-es represents oneOfKind fields.

}

function ContextTreeView(context: Struct | undefined) {
function ContextTreeView(context: JsonObject | undefined) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The value of a Struct on a message is just a JsonObject as far as client code is concerned, so we convert these functions to handle them.

}),
true,
];
function ContextTreeValue(value: JsonValue) {
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 function needed to change a bit - rather than switching on a string field, we switch on the type of the value itself.

Comment on lines +492 to +502
let checkResult: CheckOperationsResult = create(
CheckOperationsResultSchema,
{
membership: CheckOperationsResult_Membership.UNKNOWN,
},
);
request?.check(
create(CheckOperationParametersSchema, {
resource: relationship.resourceAndRelation!,
subject: relationship.subject!,
},
}),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Rather than the message types having their own constructors, you have a Schema object that you hand to a create function. It's a little more verbose in some ways, but the create function lets you pass in normal JS objects and it Just Works, which is nifty.

if (
status.code ===
LookupShareResponse_LookupStatus.FAILED_TO_LOOKUP.toString()
response.status === LookupShareResponse_LookupStatus.FAILED_TO_LOOKUP
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Shape change - status is on the object.

: "",
expiration: rel.optionalExpirationTime
? new Date(parseFloat(rel.optionalExpirationTime.seconds) * 1000)
? timestampDate(rel.optionalExpirationTime)
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 is another nicety - there are some utility functions around well-known types, so we don't have to manually parse out the representations of Timestamps.

Comment on lines -181 to 169
expect(parsed?.caveat?.caveatName).toBe("somecaveat");
expect(parsed?.caveat?.context).toHaveProperty("fields");
expect(parsed?.caveat?.context).toEqual({
fields: {
hi: {
kind: {
oneofKind: "stringValue",
stringValue: "there",
},
},
},
});
assert(parsed?.caveat?.context);
expect(Struct.toJson(parsed?.caveat?.context)).toEqual({ hi: "there" });
expect(parsed?.caveat?.context).toEqual({ hi: "there" });
});
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 is a concrete illustration of how Structs changed.

const encodedResponse: string = window[ENTRYPOINT_FUNCTION](
DeveloperRequest.toJsonString(request),
const developerRequest = JSON.stringify(
toJson(DeveloperRequestSchema, request),
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Somewhat confusingly, toJson returns a JS object, not a JSON string.

@tstirrat15 tstirrat15 marked this pull request as ready for review May 25, 2025 13:55
Copy link

@alecmerdler alecmerdler left a comment

Choose a reason for hiding this comment

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

Very cool

@tstirrat15 tstirrat15 merged commit c1c5768 into main May 27, 2025
5 checks passed
@github-actions github-actions bot locked and limited conversation to collaborators May 27, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dogfood protobuf-es

3 participants