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

Issue generating code with v2.0 #957

Closed
Evilu opened this issue Aug 4, 2024 · 11 comments
Closed

Issue generating code with v2.0 #957

Evilu opened this issue Aug 4, 2024 · 11 comments

Comments

@Evilu
Copy link

Evilu commented Aug 4, 2024

Hi,
version 2.0.0 broke my app completely, now each response throwing me the
"TS2693: xxResponse only refers to a type, but is being used as a value here." error.
In the generated type in service_pb_d.ts file it says:TS2344: Type string does not satisfy the constraint.

any clue?

EDIT:
here is an example:

app
-protos
--com
---app
----tab
-----documents
------v1
-------document.proto
-------document_service.proto
--google
---api
----field_behavior.proto

document.proto:

syntax = "proto3";

package com.app.tab.documents.v1;

import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";

// Represents a document associated with a patient.
message Document {
  // Document id, globally unique
  optional int64 id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // User id associated with the document
  optional int64 user_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Visit id associated with the document
  optional int64 visit_id = 3 [(google.api.field_behavior) = REQUIRED];

  // Document creation date
  optional google.protobuf.Timestamp creation_date = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Title of the document
  optional string title = 5 [(google.api.field_behavior) = REQUIRED];

  // Description of the document
  optional string description = 6;

  // URL or file path of the document
  optional string document_url = 7 [(google.api.field_behavior) = REQUIRED];
}

document_service.proto:

syntax = "proto3";

package com.app.tab.documents.v1;

import "google/api/field_behavior.proto";
import "google/protobuf/timestamp.proto";

// Represents a document associated with a patient.
message Document {
  // Document id, globally unique
  optional int64 id = 1 [(google.api.field_behavior) = OUTPUT_ONLY];

  // User id associated with the document
  optional int64 user_id = 2 [(google.api.field_behavior) = REQUIRED];

  // Visit id associated with the document
  optional int64 visit_id = 3 [(google.api.field_behavior) = REQUIRED];

  // Document creation date
  optional google.protobuf.Timestamp creation_date = 4 [(google.api.field_behavior) = OUTPUT_ONLY];

  // Title of the document
  optional string title = 5 [(google.api.field_behavior) = REQUIRED];

  // Description of the document
  optional string description = 6;

  // URL or file path of the document
  optional string document_url = 7 [(google.api.field_behavior) = REQUIRED];
}

buf.gen.yaml:

version: v1
plugins:
  # TypeScript
  - plugin: buf.build/connectrpc/es:v1.1.3
    out:  protos/protobufGen
  # dependencies
  - plugin: buf.build/bufbuild/es
    out: protos/protobufGen

api:
documents.ts:

import {
    ListDocumentsRequest,
    ListDocumentsResponse
} from './protos/protobufGen/com/app/tab/documents/v1/document_service_pb';

import {Code, ConnectError} from '@connectrpc/connect';

export const listDocuments = async (call: ListDocumentsRequest): Promise<ListDocumentsResponse> => {
    try {
        if (call.folderId) {
            const obj = {
                "id": call.folderId,
                "user_id": 0,
                "visit_id": 0,
                "creation_date": "1970-01-01T00:00:00Z",
                "title": "",
                "description": "",
                "document_url": ""
            }

            return new ListDocumentsResponse({
                documents: obj,
            });
        }
        throw new ConnectError("MISSING DocID", Code.InvalidArgument);
    } catch (error) {
        const errorMessage = error instanceof Error ? error.message : "FATAL ERROR";
        throw new ConnectError(JSON.stringify(errorMessage), Code.Internal);
    }
};

image

image

EDIT2:
apparently downgrade is not possible.
i was trying to use last version

package.json:

 "devDependencies": {
    "@bufbuild/protoc-gen-es": "1.3.3",
    "@bufbuild/buf": "1.34.0"
  },

npm cache clean --force && npm install

and still the code seems to be generate by v2.0.0, so i'm pretty stuck.
image

@UntakerAnonPLAY
Copy link

Similar problems happened to me as well. I just started using the lib and connect, but no types were working and generated ts seemed very odd to me (types were values and so on). For me the solution was to get the previous version (1.10.0), cause they introduced "breaking" changes)

@Evilu
Copy link
Author

Evilu commented Aug 5, 2024

Similar problems happened to me as well. I just started using the lib and connect, but no types were working and generated ts seemed very odd to me (types were values and so on). For me the solution was to get the previous version (1.10.0), cause they introduced "breaking" changes)

Of course, the problem is that I can't downgrade, I think they released protoc-gen-es 2.0.0 for all their old versions,
And that's explains why the major version was installed on my machine (^ Caret should prevent the installation of major versions).

I did a little experiment and installed everything in a new alpine environment with docker and then I tried to print the first line of the generated file and look what I got.

package.json:

{
  "name": "protoclass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "devDependencies": {
    "@bufbuild/buf": "1.30.1",
    "@bufbuild/protoc-gen-es": "1.10.0"
  },
  "author": "",
  "license": "ISC"
}

.dockerfile:

# Use an official Node.js runtime as the base image
FROM node:latest AS builder

# Set the working directory in the container to /app
WORKDIR /app

# Copy package.json and package-lock.json to the working directory
COPY package*.json ./

# Install all the dependencies
RUN npm install

# Copy the rest of the code to the working directory
COPY . .

# Generate the protobuf files
RUN npx buf generate ./protos

# Use a lightweight shell, like Alpine, to read the version from document_service_pb.d.ts
FROM alpine

# Copy the file from the Node.js image to the Alpine image
COPY --from=builder /app/protos/protobufGen/com/app/tab/documents/v1/document_service_pb.d.ts .

# Print the version from the top of document_service_pb.d.ts
CMD head -n 1 document_service_pb.d.ts
image

@UntakerAnonPLAY
Copy link

"I think they released protoc-gen-es 2.0.0 for all their old versions", what do you mean by that? Cause I just also made some tests with bun (I am not using node for this project) and it did install previous version. At least if you understood you correctly, it doesn't make any sense

@UntakerAnonPLAY
Copy link

image

@UntakerAnonPLAY
Copy link

image Just tested on node, same result as with bun

@Evilu
Copy link
Author

Evilu commented Aug 5, 2024

Thats super strange honestly.
iv'e pushed the example, may you spot the fault point i'm missing?
https://github.com/Evilu/protoClass

@smaye81
Copy link
Member

smaye81 commented Aug 5, 2024

Hey, everyone, hopefully I can help sort out the issues here. First, a v2.0.0 was released for the following packages:

  • @bufbuild/protobuf
  • @bufbuild/protoc-gen-es
  • @bufbuild/protoplugin

However, no v2 for any @connectrpc has yet been released, so if you are using @connectrpc packages, you will want to pin to the v1.x versions of the @bufbuild packages I listed above. The latest v1.x version is 1.10.0, so using ^1.10.0 in your package.json should work for your @bufbuild deps. Also what @UntakerAnonPLAY listed above works, too.

@Evilu in your protoClass example, it looks like you are using the remote plugin for bufbuild/es and not specifying a dependency, which will give you the latest version (i.e. v2.0.0), so you will also want to pin to a version in your buf.gen.yaml. Try this instead:

- plugin: buf.build/bufbuild/es:v1.10.0

@Evilu
Copy link
Author

Evilu commented Aug 5, 2024

@Evilu in your protoClass example, it looks like you are using the remote plugin for bufbuild/es and not specifying a dependency, which will give you the latest version (i.e. v2.0.0), so you will also want to pin to a version in your buf.gen.yaml. Try this instead:

- plugin: buf.build/bufbuild/es:v1.10.0

that did the trick!
for some reason this buf.gen.yaml:

version: v1
plugins:
  # TypeScript
  - plugin: buf.build/connectrpc/es:v1.1.3
    out:  protos/protobufGen
  # dependencies
  - plugin: buf.build/bufbuild/es
    out: protos/protobufGen

gave me protoc-gen-es 2.0.0 no matter the version the the pacakge.json

and this one:

version: v1
plugins:
  # TypeScript
  - plugin: buf.build/connectrpc/es:v1.1.3
    out:  protos/protobufGen

seems to do the trick (And I say this carefully before I tested the whole api, but at least it gave me files generated with protoc-gen-es 1.1.3)

I have to say that this is quite strange behavior and deserves to be investigated.
Also,
In the future I would suggest conducting thorough deep checks before releasing any major version, especially when it is such a cornerstone dependency that many other components rely on.

@smaye81
Copy link
Member

smaye81 commented Aug 5, 2024

gave me protoc-gen-es 2.0.0 no matter the version the the pacakge.json

Yeah this is because you're using a remote plugin to generate your code which is completely independent of the plugin version you've specified in your package.json. If you were using a local plugin to generate the code, then they would be the same because when running generate, it would look in your path for the plugin executable. When generating code remotely, it uses the executable version you've specified in your buf.gen.yaml. If you do not specify a version, then it pulls the latest plugin version available at the time of generating.

You actually do not even need to have protoc-gen-es as a dependency if you are using remote plugins.

More on code generation here.

@smaye81 smaye81 changed the title TS2693: xxResponse only refers to a type, but is being used as a value here. Issue generating code with v2.0 Aug 5, 2024
@smaye81
Copy link
Member

smaye81 commented Aug 5, 2024

@Evilu going to close this issue, but feel free to reopen if you see other issues. FWIW, we plan to address this for the future so that users aren't inadvertently broken when a new major plugin version is released.

@Evilu
Copy link
Author

Evilu commented Aug 6, 2024

@Evilu going to close this issue, but feel free to reopen if you see other issues. FWIW, we plan to address this for the future so that users aren't inadvertently broken when a new major plugin version is released.

Thanks for the help, everything is much clearer now.

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

No branches or pull requests

3 participants