stephenh / ts-proto

An idiomatic protobuf generator for TypeScript
Apache License 2.0
2.17k stars 349 forks source link

generate only gPRC client related code in nestJs=true #527

Open mpx2m opened 2 years ago

mpx2m commented 2 years ago

If there is proto like this:

// demo.proto
syntax = "proto3";
package proto.v1;

service TestService {
    rpc Login (LoginRequest) returns (LoginResponse);
}

message LoginRequest {
    string name = 1;
    string password = 2;
}

message LoginResponse {
    string auth_code = 1;
}

after

"protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_opt=outputPartialMethods=true --ts_proto_opt=nestJs=true --ts_proto_opt=env=node --ts_proto_opt=addGrpcMetadata=true --ts_proto_opt=useOptionals=messages --ts_proto_opt=forceLong=string --ts_proto_opt=unrecognizedEnum=false --ts_proto_out=./ demo.proto"

produce

/* eslint-disable */
import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
import { util, configure } from "protobufjs/minimal";
import * as Long from "long";
import { Observable } from "rxjs";
import { Metadata } from "@grpc/grpc-js";

export const protobufPackage = "proto.v1";

/** demo.proto */

export interface LoginRequest {
  name: string;
  password: string;
}

export interface LoginResponse {
  authCode: string;
}

export const PROTO_V1_PACKAGE_NAME = "proto.v1";

export interface TestServiceClient {
  login(request: LoginRequest, metadata?: Metadata): Observable<LoginResponse>;
}

export interface TestServiceController {
  login(
    request: LoginRequest,
    metadata?: Metadata
  ): Promise<LoginResponse> | Observable<LoginResponse> | LoginResponse;
}

export function TestServiceControllerMethods() {
  return function (constructor: Function) {
    const grpcMethods: string[] = ["login"];
    for (const method of grpcMethods) {
      const descriptor: any = Reflect.getOwnPropertyDescriptor(
        constructor.prototype,
        method
      );
      GrpcMethod("TestService", method)(
        constructor.prototype[method],
        method,
        descriptor
      );
    }
    const grpcStreamMethods: string[] = [];
    for (const method of grpcStreamMethods) {
      const descriptor: any = Reflect.getOwnPropertyDescriptor(
        constructor.prototype,
        method
      );
      GrpcStreamMethod("TestService", method)(
        constructor.prototype[method],
        method,
        descriptor
      );
    }
  };
}

export const TEST_SERVICE_NAME = "TestService";

// If you get a compile-error about 'Constructor<Long> and ... have no overlap',
// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'.
if (util.Long !== Long) {
  util.Long = Long as any;
  configure();
}

In some NestJs project, only gRPC client is implemented and generated code with *Controller, *ControllerMethods related (TestServiceController, TestServiceControllerMethods above) are unwanted in this situation.

So a flag that can be set to only generate gPRC client related code would be nice.

After set the flag, the proto file above will produce code like:

/* eslint-disable */
import { util, configure } from "protobufjs/minimal";
import * as Long from "long";
import { Observable } from "rxjs";
import { Metadata } from "@grpc/grpc-js";

export const protobufPackage = "proto.v1";

/** demo.proto */

export interface LoginRequest {
  name: string;
  password: string;
}

export interface LoginResponse {
  authCode: string;
}

export const PROTO_V1_PACKAGE_NAME = "proto.v1";

export interface TestServiceClient {
  login(request: LoginRequest, metadata?: Metadata): Observable<LoginResponse>;
}

export const TEST_SERVICE_NAME = "TestService";

// If you get a compile-error about 'Constructor<Long> and ... have no overlap',
// add '--ts_proto_opt=esModuleInterop=true' as a flag when calling 'protoc'.
if (util.Long !== Long) {
  util.Long = Long as any;
  configure();
}
stephenh commented 2 years ago

@mpx2m hm, yeah, that makes sense. I think that nestJs=true is already kind of a meta-option that sets some other parameters; see around here:

https://github.com/stephenh/ts-proto/blob/main/src/options.ts#L113

If you'd like to submit a PR that adds nestJs=client & nestJs=server support, that'd be great.

If so, I'd suggest doing it like this PR:

https://github.com/stephenh/ts-proto/pull/512

I.e. turn the internal Options.nestJs into an array of options.nestJs: Array<'client' | 'server'> and then update optionsFromParameter to watch for nestJs=true and turn that into nestJs: ['client', 'server'].

Thanks!

MaksymShuldiner commented 1 year ago

+1 for that