Getting Started
Install
bash
npm install -g proto-codegen
# or
pnpm add -g proto-codegenCreate a config file
Add proto-codegen.config.json to your project root:
json
{
"input": {
"protoDir": "./proto",
"include": ["*.proto"],
"exclude": ["*_test.proto"]
},
"output": {
"dir": "./generated",
"clientsDir": "clients",
"typesDir": "types"
},
"generation": {
"generateTypes": true,
"generateClients": true
}
}Add your proto files
Put .proto files in ./proto. The tool reads google.api.http annotations to build the HTTP client:
protobuf
syntax = "proto3";
package example;
message GetUserRequest {
string user_id = 1;
}
message GetUserResponse {
string id = 1;
string name = 2;
string email = 3;
}
service UserService {
rpc GetUser(GetUserRequest) returns (GetUserResponse) {
option (google.api.http) = {
get: "/api/v1/users/{user_id}"
};
}
}Generate
bash
proto-codegen generateOutput structure:
generated/
├── index.ts
├── clients/
│ ├── index.ts
│ ├── http-client.ts
│ └── user-client.ts
└── types/
├── index.ts
└── example.tsUse it from your frontend
The generator also outputs an HttpClient interface (in generated/clients/http-client.ts) — implement it once with the HTTP library you already use (fetch, axios, etc.) and every generated client is ready to go:
typescript
import { HttpClient } from './generated/clients/http-client';
// Implement the generated interface with your HTTP library — just once
class MyHttpClient implements HttpClient {
async get<T>(url: string, params?: any): Promise<T> {
const res = await fetch(url + '?' + new URLSearchParams(params));
return res.json();
}
// post, put, delete, patch...
}Now create a client and call it — params and return type are inferred from the proto:
typescript
import { UserServiceClient } from './generated/clients/user-client';
const userService = new UserServiceClient(new MyHttpClient());
const user = await userService.getUser({ userId: '123' }); // typed as GetUserResponse
console.log(user.id, user.name, user.email);Need to unwrap { code, data, message } response wrappers, or add a path prefix? See Using generated code.
What you need installed
Type generation shells out to protoc with the ts-proto plugin, so both need to be on your PATH:
- protoc (Protocol Buffers compiler)
ts-protois pulled in as a dependency, but itsprotoc-gen-ts_protobinary must be resolvable
The client layer has no such requirement. It runs anywhere Node 18+ does.
Next steps
- Configuration reference for every available option
- CLI commands for generate, publish, link and unlink
- Using generated code for implementing the HTTP client and response unwrapping
- Playground to try it in the browser