contrib icon indicating copy to clipboard operation
contrib copied to clipboard

entproto: fix service.List pageToken for custom fields (UUID/string)

Open kdevo opened this issue 6 months ago • 1 comments

Motivation

The current List service template generates faulty code if a custom GoType field is used (currently only UUID and string types are supported by this fix).

I haven't tested this on a large set of inputs and probably I'm lacking context why the pageToken has been implemented this way (also why it is Base64-encoded), but using a call to the field_to_ent template hopefully leads to a more sane behavior, as it is also used for Get() and Update() templates.

Example schema

Example 1: UUID type

		field.UUID("id", PULID{}).
			Default(func() PULID { return MustNewPULID(m.prefix) }).
			Annotations(
				entproto.Field(1)),
			),

Example 2: String type

		field.Bytes("id").
		 	GoType(PULID{}).
		 	DefaultFunc(func() PULID { return MustNewPULID(m.prefix) }).
		 	Annotations(
		 		entproto.Field(1, entproto.Type(descriptorpb.FieldDescriptorProto_TYPE_STRING)),
		 	).

Diff of rendered code

IDLTE only accepts custom type (in this case pulid.PULID). Therefore the green lines are working code:

	if req.GetPageToken() != "" {
		bytes, err := base64.StdEncoding.DecodeString(req.PageToken)
		if err != nil {
			return nil, status.Errorf(codes.InvalidArgument, "page token is invalid")
		}
-		pageToken, err := uuid.ParseBytes(bytes)
-		if err != nil {
-			return nil, status.Errorf(codes.InvalidArgument, "page token is invalid")
-		}
+		pageToken := pulid.PULID{}
+		if err := (&pageToken).Scan(bytes); err != nil {
+			return nil, status.Errorf(codes.InvalidArgument, "invalid argument: %s", err)
+		}
		listQuery = listQuery.
			Where(evcharger.IDLTE(pageToken))
	}

Alternatives

It would probably be cleaner to allow implementing UnmarshalProto/MarshalProto for custom types similar like we can implement a custom UnmarshalGQL/MarshalGQL. The reasoning is that the Valuer/Scanner interface used by the database driver is not necessarily what we want to represent in the protobuf types.

kdevo avatar Aug 03 '24 12:08 kdevo