An open API service indexing awesome lists of open source software.

https://github.com/varavelio/vdl-plugin-rpc-go

Plugin to generate VDL RPC for Golang
https://github.com/varavelio/vdl-plugin-rpc-go

api codegen go golang rpc varavel vdl vdl-plugin vdl-rpc

Last synced: 14 days ago
JSON representation

Plugin to generate VDL RPC for Golang

Awesome Lists containing this project

README

          


VDL logo

VDL RPC Golang Plugin


Generate Go RPC clients and RPC servers from annotation-based VDL services.



A Varavel project


VDL Plugin

This plugin is RPC-focused.

It does not generate Go data models (types/enums/constants). Instead, it reuses the types generated by [`varavelio/vdl-plugin-go`](https://github.com/varavelio/vdl-plugin-go).

## Quick Start

1. Generate Go types first with `varavelio/vdl-plugin-go`.
2. Generate the RPC client package (`target "client"`) and/or server package (`target "server"`).
3. Run your normal VDL generation command (example: `vdl generate`).

```vdl
const config = {
version 1
plugins [
{
src "varavelio/vdl-plugin-go@v0.1.3"
schema "./schema.vdl"
outDir "./internal/types"
options {
package "types"
}
}
{
src "varavelio/vdl-plugin-rpc-go@v0.1.2"
schema "./schema.vdl"
outDir "./internal/client"
options {
package "client"
target "client"
typesImport "example.com/project/internal/types"
}
}
{
src "varavelio/vdl-plugin-rpc-go@v0.1.2"
schema "./schema.vdl"
outDir "./internal/server"
options {
package "server"
target "server"
typesImport "example.com/project/internal/types"
}
}
]
}
```

If you only need one side, keep only one RPC plugin block (`client` or `server`).

## Plugin Options

| Option | Type | Required | Default | What it changes |
| ------------- | -------- | -------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `target` | `string` | yes | - | Selects generation target. Must be `client` or `server`. |
| `typesImport` | `string` | no | - | Go import path for the package generated by `varavelio/vdl-plugin-go`. When omitted/empty, RPC types are resolved from the same package. |
| `package` | `string` | no | `vdlrpc` | Sets the package name used in generated RPC files (must be a valid Go package). |
| `jsonPackage` | `string` | no | `encoding/json` | Sets the Go package used for JSON marshal/unmarshal. It is always imported as `json "..."`. |

### `typesImport` behavior

- Omitted or empty (`""`): same-package mode. Generated code does not emit a types import and uses direct type names like `MessagesSendInput`.
- Non-empty: imported-types mode. Generated code imports `typesImport` as `vdltypes` and uses `vdltypes.MessagesSendInput`.

Use same-package mode when you generate Go types and RPC output into the same package. Use imported-types mode when RPC is generated in a different package.

### `jsonPackage` behavior

- Omitted: generated code imports `encoding/json` as `json`.
- Non-empty: generated code imports the configured package as `json`.
- Empty or whitespace-only: falls back to `encoding/json`.

This matches the native Go plugin behavior and lets you swap in compatible JSON implementations like `github.com/goccy/go-json` without changing generated call sites.

## Generated Files

- `target "client"` writes `client.go`.
- `target "server"` writes `server.go`.
- If your schema has no discovered `@rpc`, `@proc` or `@stream` operations, no RPC file is emitted.

## What You Get

For `target "client"`:

- `NewClient(baseURL).Build()` to create a typed RPC client.
- Typed procedure builders and stream builders under `client.RPCs.()`.
- Headers and header providers at global, RPC, and operation levels.
- Interceptors, retry/timeout policies for procs, reconnect policies for streams.
- Stream lifecycle hooks and max message size controls.

For `target "server"`:

- `NewServer[Props]()` with typed handler contexts.
- Typed registration APIs for procedures and streams.
- Middleware support at global, RPC, procedure, stream, and stream-emit levels.
- `SetStreamConfig` and `SetErrorHandler` at global and RPC scope.
- `NewNetHTTPAdapter(...)` + `HandleRequest(...)` integration for `net/http`.

Both targets also include generated operation catalogs:

- `VDLPaths` for static operation paths.
- `VDLProcedures` and `VDLStreams` with operation metadata.
- Non-marker operation annotations preserved as `Annotation` values.

## RPC Annotation Model

This plugin follows the VDL RPC annotation model:

- `@rpc` marks a top-level type as an RPC service.
- `@proc` marks a field as a request-response operation.
- `@stream` marks a field as a server-streaming operation.

```vdl
@rpc
type Messages {
@proc
send {
input {
roomId string
text string
}

output {
accepted bool
}
}

@stream
events {
input {
roomId string
}

output {
text string
}
}
}
```

Validation rules enforced by the plugin:

- `@rpc` types must be objects.
- An operation field can be `@proc` or `@stream`, but not both.
- Operation nodes must be objects.
- `input` and `output`, when present, must be objects.

If an operation omits `input` and/or `output`, generated code uses `Void` for the missing payload.

## Minimal Usage Example

```go
package main

import (
"context"
"net/http"

rpcclient "example.com/project/internal/client"
rpcserver "example.com/project/internal/server"
vdltypes "example.com/project/internal/types"
)

func example() {
server := rpcserver.NewServer[struct{}]()

server.RPCs.Messages().Procs.Send().Handle(
func(c *rpcserver.MessagesSendHandlerContext[struct{}]) (vdltypes.MessagesSendOutput, error) {
return vdltypes.MessagesSendOutput{Accepted: true}, nil
},
)

mux := http.NewServeMux()
mux.HandleFunc("POST /rpc/{rpc}/{operation}", func(w http.ResponseWriter, r *http.Request) {
adapter := rpcserver.NewNetHTTPAdapter(w, r)
_ = server.HandleRequest(r.Context(), struct{}{}, r.PathValue("rpc"), r.PathValue("operation"), adapter)
})

client := rpcclient.NewClient("http://localhost:8080/rpc").Build()
_, _ = client.RPCs.Messages().Procs.Send().Execute(
context.Background(),
vdltypes.MessagesSendInput{RoomId: "room-1", Text: "hello"},
)
}
```

`baseURL` in `NewClient(baseURL)` should point to your RPC prefix (for example: `/rpc`). The generated client appends `/{RPC}/{operation}` automatically.

## License

This plugin is released under the MIT License. See [LICENSE](LICENSE).